It’s GUID To See You CMD er…. August 28, 2012

It’s been far too long as always. New projects, new pits, but every now and then you realize how much you take some things for granted have to improvise from scratch.

I was tasked with modifying an old cmd script to add an event log entry at the beginning of the scripts run and an event log entry when it completed. To avoid cluttering the Application event log or one of the other default event logs that I lovingly refer to as event junk drawers, I created my own log with the New-EventLog cmdlet in PowerShell. After that, I added calls at the beginning and end of the cmd script that ran powershell.exe using the -Command argument and passed a short block of powershell commands.

What I did not forsee was the possibility of the cmd script running concurrently with an already running instance of the script, thus jumbling the logs and making it impossible to match a start log with its correct end log entry. I needed some way to uniquely identify each set of logs. That’s when I came up with my guid idea! (get it? good idea = guid idea… forgive the pun, I promise it will be the last)

That’s right, if I generated a guid in the cmd script and stamped that same guid in the start and end event log entries, I could match them up later. If this was a pure PowerShell script, I could simply call the [System.GUID]::NewGUID() .Net function and walk away. Unfortunately, cmd scripting leaves a little to be desired in terms of flexibility, so I broke out my old command scripting references, fired up Bing and went to work.

A GUID is a random string made up of 32 hexadecimal digits grouped in a {8-4-4-4-12} format. My first step was to get a random number in a cmd script. Enter the %random% variable. When evaluated by the command interpreter, %random% returns a (pseudo)random number between 0 and 32768. Applying a modular operator gave me my pseudo-random hexadecimal digit in decimal format.

set /a tempdec=16*%random%/32768
echo %tempdec%

Pass that decimal number through a set of cmd if statements and out pops a proper pseudo-random hexadecimal digit. I present the hex-o-matic pseudo-random number generator:

Now I just need 31 more. My first instinct was to drop my pseudo-random hex-o-matic code inside of the cmd script version of a iterative for loop

FOR /L %a (1,1,32) do ACTION

and call it a day. Unfortunately, that was too easy. %random% uses the current time as its seed, and when the FOR command is run, it gets the time at launch and provides that time value to the code in its care every time it is requested. That means that %random% uses the same time value and generates the same pseudo-random number every time it is called in the FOR command.

There was only one thing to be done, 32 successive hex-o-matic blocks stacked end to end, each adding one hexadecimal digit to the guid.

Now I had a wonderful string of 32 hex digits in a row. Enter the cmd script substring syntax: %VARIABLE:~[STARTINDEX],[NUMBEROFCHARS]%

So we take our %GUID% string and…

set GUIDF={%GUID:~0,8%-%GUID:~8,4%-%GUID:~12,4%-%GUID:~16,4%-%GUID:~20,12%}

VOILA! Out pops

{329674F9-97A7-CC6C-A0DA-DB21ED8EA0D3}

So the next time you whine about how PowerShell should include a Get-GUID cmdlet, just remember, it used to take 577 lines of cmd script to accomplish what $GUID = [System.GUID]::NewGUID() does in one. Ain’t the future grand?