Here we go!
Comments closedPaul Williams' Tech Blog
Here we go!
Comments closedIn my current job, I have to wrestle with getting a variety of software programs installed in a lab environment in a completely automated way. Some software makes this easier than others. Minitab used to be one of the easier ones, but with version 18 it has become a little harder.
As far as I can remember, when you silently installed Minitab 17 with a network license there was no need to register it on the first run. (I could be mistaken, but my notes from last year don’t indicate I had to do anything special.) With Minitab 18 you must register with an email address, first name, and last name on the first launch. I could almost handle this by including it in the image I capture, but I prefer to install small programs like this at the time of deployment.
After a bit of investigating and testing, I’ve found a way to get around this registration requirement on first launch. All you need to do is drop a file named License.ini in C:\ProgramData\Minitab with the following contents:
1 2 3 4 5 6 |
[Minitab 18] EMail={enter email address here} firstName={enter a first name here} lastName={enter a last name here} |
That’s it. On first launch Minitab 18 will see these prepopulated items, fill in the remaining items, and move on as if it were already registered. I’m not sure if anything is case sensitive or if the blank lines are required, but I know what I’ve listed above works for me. The email address you enter should be of valid format but it doesn’t need to be an actual address. For example, [email protected] will work just fine. Here’s a sample completed file:
1 2 3 4 5 6 |
[Minitab 18] EMail=computerlab@university.edu firstName=Computer lastName=Lab |
I’ve been working on completely automating the creation, capture, and testing of reference images using the Microsoft Deployment Toolkit (at version 2013 Update 2 as of this writing). The first two parts are straightforward and it’s easy to find guides on how to do that. However, I wanted to automate my process even more by having my newly captured image deployed to a test virtual machine and an email sent to let me know when it’s ready to check. At this point, all I need to do is verify that things work as expected in the VM and adjust my production task sequences to use the new OS if it all checks out.
Importing a new OS is easy. There’s a PowerShell commandlet for that included in the MDT tools. Importing a new task sequence is easy, too. There’s a commandlet for that.
What’s not so easy is editing a task sequence that already exists using PowerShell. In fact, I found very little online about how to do this – and nothing about how to change the OS of a task sequence. Nickolaj Andersen has a good post on using PowerShell to modify settings in MDT where he does change a task sequence, but he was simply turning Windows Updates off. And this guy asked how to modify the OS of a task sequence using PowerShell on TechNet but did not get a satisfactory answer in my opinion. But between Nickolaj’s post and some tinkering, I was able to get it working and finish automating those final bits of my process.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
Import-Module "C:\Program Files\Microsoft Deployment Toolkit\bin\MicrosoftDeploymentToolkit.psd1" # Variables you need to define $MDT_Build_Path = "D:\MDT_Build" $MDT_Prod_Path = "D:\MDT_Production" $RefTaskID = "REFW10-X64-001" $ProdTaskID = "PRODW10-X64-001" $TestTaskID = "TESTW10-X64-001" $OS = "Windows 10" # End user defined variables $Build_Captures_Path = $MDT_Build_Path + "\Captures" $Prod_Control_Path = $MDT_Prod_Path + "\Control" # Get the file name of the most recent capture $RefImg = Get-ChildItem $Build_Captures_Path -Filter ($RefTaskID + "*") | Sort LastWriteTime | Select -Last 1 # Drop .wim from name and save to separate variable $RefImgOSName = $RefImg.Name.Replace('.wim','') # Set up PSDrive to Production Deployment Share New-PSDrive -Name "DS002" -PSProvider MDTProvider -Root $MDT_Prod_Path # Import RefImg to Production DS Operating Systems Import-MDTOperatingSystem -Path "DS002:\Operating Systems\$($OS)" -SourceFile $RefImg.FullName -DestinationFolder $RefImgOSName # Rename the Operating System to clean it up $RefImgOSCurrentName = Get-ChildItem "DS002:\Operating Systems\$($OS)" | Where {$_.Name -like "* in *"} Rename-Item -Path "DS002:\Operating Systems\$($OS)\$($RefImgOSCurrentName.Name)" -NewName $RefImgOSName # Get GUID of OS $RefImgOSguid = (Get-ItemProperty "DS002:\Operating Systems\$($OS)\$($RefImgOSName)").guid # Delete RefImg Capture from Build DS Remove-Item $RefImg.FullName -Force # Copy Production TS to Test TS Copy-Item "$Prod_Control_Path\$($ProdTaskID)\*" "$Prod_Control_Path\$($TestTaskID)" -Force # Modify Test Task Sequence to use new RefImg OS $TSPath = "$Prod_Control_Path\$TestTaskID\ts.xml" $TSXML = [xml](Get-Content $TSPath) $TSXML.sequence.globalVarList.variable | Where {$_.name -eq "OSGUID"} | ForEach-Object {$_."#text" = $RefImgOSguid} $TSXML.sequence.group | Where {$_.Name -eq "Install"} | ForEach-Object {$_.step} | Where { $_.Name -eq "Install Operating System"} | ForEach-Object {$_.defaultVarList.variable} | Where { $_.name -eq "OSGUID"} | ForEach-Object {$_."#text" = $RefImgOSguid} $TSXML.Save($TSPath) |
I should note that I have pulled these lines out of a function I use in my process. This is not the ideal way to structure this code, but I thought it would be easiest for others to use this way.
I included more of the code than you need just for editing the XML of the task sequence (see lines 44-50 for the most relevant bits). I thought a little context might help.
Most of this should be self-explanatory, but I’ll mention a few things to clarify why I have things set up the way I do. First, I’m assuming you have two separate deployment shares – one for building images and one for deploying them (a.k.a. production). I have my test task sequences in my production share, but I have them in a folder that’s disabled so no one sees them in the list of task sequence options during a deployment.
Second, line 19 assumes that your captured images include your task sequence ID in the name of the .wim file. That’s easy to do in customsettings.ini (see step 7 here for the BackupFile setting).
18 19 |
# Get the file name of the most recent capture $RefImg = Get-ChildItem $Build_Captures_Path -Filter ($RefTaskID + "*") | Sort LastWriteTime | Select -Last 1 |
Third, lines 28, 31, 32, and 35 assume that you have structured your Operating Systems folder to separate out your imported OSes rather than throwing them all in the root folder. If that’s not what you do, then you’ll need to modify those parts.
27 28 29 30 31 32 33 34 35 |
# Import RefImg to Production DS Operating Systems Import-MDTOperatingSystem -Path "DS002:\Operating Systems\$($OS)" -SourceFile $RefImg.FullName -DestinationFolder $RefImgOSName # Rename the Operating System to clean it up $RefImgOSCurrentName = Get-ChildItem "DS002:\Operating Systems\$($OS)" | Where {$_.Name -like "* in *"} Rename-Item -Path "DS002:\Operating Systems\$($OS)\$($RefImgOSCurrentName.Name)" -NewName $RefImgOSName # Get GUID of OS $RefImgOSguid = (Get-ItemProperty "DS002:\Operating Systems\$($OS)\$($RefImgOSName)").guid |
Finally, the last seven lines show how to modify the OS of a given task sequence. There are three spots where the GUID of the OS is stored in the task sequence. I found two listings in Sequence.GlobalVarList.variable and one in Sequence.Group(Install).Step(Install Operating System).defaultVarList.variable. Change those, save the XML, and you’re done. Your test task sequence will now point to your newly captured OS.
43 44 45 46 47 48 49 50 |
# Modify Test Task Sequence to use new RefImg OS $TSPath = "$Prod_Control_Path\$TestTaskID\ts.xml" $TSXML = [xml](Get-Content $TSPath) $TSXML.sequence.globalVarList.variable | Where {$_.name -eq "OSGUID"} | ForEach-Object {$_."#text" = $RefImgOSguid} $TSXML.sequence.group | Where {$_.Name -eq "Install"} | ForEach-Object {$_.step} | Where { $_.Name -eq "Install Operating System"} | ForEach-Object {$_.defaultVarList.variable} | Where { $_.name -eq "OSGUID"} | ForEach-Object {$_."#text" = $RefImgOSguid} $TSXML.Save($TSPath) |
The rest of my script boots the test VM and then the MDT database and my customsettings.ini automates the rest. The script waits for the VM to shut down at the end and emails me when it is done. Having all of this automated allows me to build a new reference image for each OS every month but only takes me a few minutes of verifying the test VMs and modifying the production task sequences.
Makes me do my happy dance.
4 Comments