David's Public Pages

There's no place like ::1

User Tools

Site Tools


archive:blog:2007_11_17

SysPrep in Depth - Part 8 - Automating your Product Keys

November 17, 2007

Automate Entering Your non-VLK Product Keys into Sysprep

- The Problem

In our environment we have 500+ computers, each with its own product key, and no VLK's at hand to use. I decided one day that typing in all these keys every time we cloned was getting old, so I sat down to find a way around the issue. I needed a database of all the product keys, and a way to map the keys to the box they came with. After finding out how to do all this I needed a way to use the keys within sysprep.

The idea behind this is to take 10+ keys, 10+ computers, a little bit of laziness, and wanting to get the clones done in a timely manor. Hang with me while I explain this as there are a few steps to getting this all to work.

- Database Elements

As we had all the computers running with their own keys already, I figured the easiest way to get the database was to get the key from the computer itself, and not have to walk around to each computer, pull the cover off and write the key down.

I pulled out a product from my toolkit that does just that, ProduKey. This free product will show you your installed keys for various MS applications and has the ability to export this list to a file. With a little scripting I could easily get an exported key for each PC, but this is far from what I needed to get this all working.

I needed a way to get this exported key to map to the computer it came from, so after a little thought, I pulled up a freshly syspreped computer and verified that I could get its MAC address during the sysprep process and guess what, “ipconfig /all” would show me exactly what I needed.

Now that I had a product key and a matching mac address, but I wanted to be able to match these two fields to the computer name.

- Getting the Database Made

Now I had an idea of what was needed and how to create it. I wanted one file that contained a list of all the MAC addresses, Product Keys, and Computer Names and to get all this without having to go touch every PC.

I decided to use AutoIt to write the program which could accomplish the following.

  1. Use ProduKey to export the computers' product key
  2. Parse the exported file to find only the Windows XP key
  3. Use “ipconfig /all” to get the computers MAC address and export this to a file
  4. Parse the exported ipconfig file to find only the mac address of the network card
  5. Grab the computer name
  6. Throw this all into an ini file for use later on

AutoIt source file to do all this:

#NoTrayIcon
Opt("RunErrorsFatal", 0)
$keyfinder_path\FileServerWindowsXP Product KeysProduKey.exe"
$product_Code_save="\FileServerWindowsXP Product KeysProductCodes.ini"
[email protected] & "product_code.txt"
[email protected] & "ipconfig.txt"
[email protected] & "mac2product.ini"
$product_Code=""
$mac_address="00-00-00-00-00-00"
$comp_Name = StringUpper(@ComputerName)
; Check that the computer matches our managed PC's, you can remove this if statement if you need
if StringLeft($comp_Name,5) = "MANAGEDNAME-" Then
; find the mac on the computer
dim $ipconfigOut = ""
$ipconfigOut = $ipconfigOut & "@echo off" & @CRLF
$ipconfigOut = $ipconfigOut & "ipconfig /all >" & $ipconfig_file
dim $ipconfigfileName = @TempDir & "ipconfig.cmd"
FileDelete ( $ipconfigfileName )
dim $file = FileOpen($ipconfigfileName, 2)
FileWrite($file, $ipconfigOut)
FileClose($file)
RunWait($ipconfigfileName, "", @SW_HIDE)
FileDelete ( $ipconfigfileName )
$file = FileOpen($ipconfig_file, 0)
If $file = -1 Then
MsgBox(266240, "Error", "Unable to open ipconfig file.",3)
Exit
EndIf
While 1
$line = FileReadLine($file)
If @error = -1 Then ExitLoop
if StringUpper(StringRight(StringLeft($line, 24),16)) = StringUpper("Physical Address") Then
$mac_address = StringUpper(StringRight($line, 17))
endif
Wend
FileClose($file)
FileDelete ( $ipconfig_file ); find the product code
dim $productCodeOut = ""
$productCodeOut = $productCodeOut & "@echo off" & @CRLF
$productCodeOut = $productCodeOut & '"' & $keyfinder_path & '" /stext "' & $Product_Code_Export & '"'
dim $productCodefileName = @TempDir & "ProduKey.cmd"
FileDelete ( $productCodefileName )
dim $file = FileOpen($productCodefileName, 2)
FileWrite($file, $productCodeOut)
FileClose($file)
RunWait($productCodefileName, "", @SW_HIDE)
FileDelete ( $productCodefileName )
if @error = 1 then exit
$file = FileOpen($Product_Code_Export, 0)
If $file = -1 Then
MsgBox(266240, "Error", "Unable to open product key export file.",3)
Exit
EndIf
While 1
$line = FileReadLine($file)
If @error = -1 Then ExitLoop
if StringUpper(StringRight(StringLeft($line, 40),20)) = StringUpper("Microsoft Windows XP") Then
$line = FileReadLine($file)
$line = FileReadLine($file)
$product_Code=StringUpper(StringRight(StringLeft($line, 49),29))
endif
Wend
FileClose($file)
FileDelete ( $Product_Code_Export )
if $mac_address="00-00-00-00-00-00" then
Else
$line = IniRead($product_Code_save, "ProductKeys", $mac_address, "NotFound") If $line = "NotFound" Then
$file = FileOpen($product_Code_save, 1)
If $file = -1 Then
Exit
EndIf
FileWriteLine($file, $mac_address & "=" & $product_Code & "," & $comp_Name)
FileClose($file)
exit
EndIf
EndIf
FileClose($file)
EndIf

If you need help with the code feel free to ask, but for now I will leave it as is. This AutoIt file uses the ProduKey file stored on our server and edits the file on the server as well. The resulting ini file looks something like this.

AA-BB-CC-DD-EE-FA=XXXXX-XXXXX-XXXXX-XXXXX-XXXX,MANAGEDNAME-COMPUTER1
AA-BB-CC-DD-EE-FB=XXXXX-XXXXX-XXXXX-XXXXX-XXXX,MANAGEDNAME-COMPUTER2
AA-BB-CC-DD-EE-FC=XXXXX-XXXXX-XXXXX-XXXXX-XXXX,MANAGEDNAME-COMPUTER3
AA-BB-CC-DD-EE-FD=XXXXX-XXXXX-XXXXX-XXXXX-XXXX,MANAGEDNAME-COMPUTER4

Now that we have our ini file we can move on to getting sysprep to use this file.

- Adding our INI to Sysprep

Unfortunately, there is no way with this method to have on-the-fly updates to our ini file being pushed out to new clones, meaning that this static database needs to be included in the image of our computers, and that it cannot be stored on a server during the sysprep process. If you know a way around this feel free to correct me, but if I remember correctly the network card drivers are installed before the product key is entered (allowing us to get the mac), but TCP/IP is installed after XP asks for the key…

Anyways, all you need to do after you have tested the above script is get it running on all your computers via a startup script or some other means. To make this a valid ini we need to add one line to the beginning of the file. We need to add a section to it called ProductKeys. To do this add “[ProductKeys]” as the first line in the ini file (without the quotes). Your ini should now look like this:

[ProductKeys]
AA-BB-CC-DD-EE-FA=XXXXX-XXXXX-XXXXX-XXXXX-XXXX,MANAGEDNAME-COMPUTER1
AA-BB-CC-DD-EE-FB=XXXXX-XXXXX-XXXXX-XXXXX-XXXX,MANAGEDNAME-COMPUTER2
AA-BB-CC-DD-EE-FC=XXXXX-XXXXX-XXXXX-XXXXX-XXXX,MANAGEDNAME-COMPUTER3
AA-BB-CC-DD-EE-FD=XXXXX-XXXXX-XXXXX-XXXXX-XXXX,MANAGEDNAME-COMPUTER4
...

Copy this edited ini file to your clone image computer and move on to the next step.

- Complications in the Process

There is a section within the sysprep.inf file for product keys, so I tried to get the sysprep.inf file edited on boot so this was all automated, but the sysprep.inf file was being cached long before I could get the key written to it. I also wanted to be able to get the ini file I was creating on the network so that I could easily update it, but as I explained earlier this was impossible with this method.

Now I had all the info I needed and no way of getting it working, so now what?

- Type the Product Key in Automatically and Dynamically

Using another AutoIt file I was able to get this ini file I created to be worth its time. Once we have the computer at the window where it is asking for the product key we can press Shift+f10 and get to a command prompt, type in “ipconfig /all”, and if we have done all our drivers right we will see our MAC address.

The following code pulls the mac address from the ini file, and the network card, and tries to find a match. If it does it pulls the product key from the ini and starts typing it in for us. This only enters in the computers product code, but as we have the computer name in or database it would be an easy edit to this code to start typing in computer names as well if we wanted.

RunWait(@ComSpec & " /c " & "ipconfig /all >" & $ipconfig_file)
$file = FileOpen($ipconfig_file, 0) If $file = -1 Then
MsgBox(266240, "Error", "Unable to open ipconfig file.")
Exit
EndIf While 1
$line = FileReadLine($file)
If @error = -1 Then ExitLoop
if StringUpper(StringRight(StringLeft($line, 24),16)) = StringUpper("Physical Address") Then
$mac_address = StringUpper(StringRight($line, 17))
funcProduct_Key()
endif
Wend
MsgBox(266240, "Error finding MAC Address", "Mac address could not be found." & @CRLF & "Network card might not be installed.", 5)
FileClose($file) Func funcProduct_Key()
$Prod_Key = StringUpper(IniRead($Prod_Key_File, "ProductKeys", $mac_address, "NotFound"))
if $Prod_Key = StringUpper("NotFound") Then
MsgBox(266240, "Product Key", "Mac address not found in database." & @CRLF & $mac_address, 10)
else
$ini_info = StringSplit($Prod_Key, ",")
$Key_Parts = StringSplit($ini_info[1], "-")
MsgBox(266240, "Computer", $ini_info[2], 2)
MsgBox(266240, "Product Key", $ini_info[1], 2)
WinActivate ( "Windows XP Professional Setup" , "" )
Send ( "!p" )
Send ($Key_Parts[1])
Send ($Key_Parts[2])
Send ($Key_Parts[3])
Send ($Key_Parts[4])
Send ($Key_Parts[5])
Send ("{ENTER}")
FileClose($file)
Exit
EndIf
EndFunc

- Putting this all Together

Once you have made the necessary edits to the .au3 files, compile them and you're ready to go.

Find a way to get your clients to start running the FindProductKey.exe; we were on a domain so creating a computer startup script made this an easy task. Once you have a list of all the computers with their MAC address, product keys, and computer names, (mac2product.ini) we can make our edit to the first line and copy this file off to our clone computer.

On our clone computers we need to place TypeProductKey.exe and mac2product.ini within the same directory. I didn't want to let someone just get a list of every product key in the building, even though it wouldn't be hard for them to do, so I placed the database of product keys in the sysprep folder so that after sysprep finishes it is automatically deleted. Once you have TypeProductKey.exe and mac2product.ini contained in your clone you can pull an image and start pushing it out. Once your clones get to the screen asking for the product key simply hit shift+f10 to get a command prompt and start-up TypeProductKey.exe.

- Other Tidbits

I wanted a basic version of mac2product.ini contained on every computer for ease but you could also keep an up-to-date version on a usb key with TypeProductKey.exe for those computers that you know were not in the cloned mac2product.ini. You can also do a fair amount of debugging using TypeProductKey.au3 and autoit3.exe from a usb drive within sysprep if you want to work with automating any other parts of sysprep.

Let me know what you thing about this process and if you have any ways to make it more refined.

archive/blog/2007_11_17.txt · Last modified: 11/17/2007 (external edit)