Michael Niehaus' Windows and Office deployment ramblings
There are two new Lite Touch task sequence templates provided in MDT 2010:
This seems to be a frequent question that comes up:
“I am working with PCs from <vendor> that have model strings that frequently change, although the first part is always consistent. How can I use these models with the MDT database without creating a new entry for each unique string?”
This seems to come up most often with computers from Lenovo, where the first four characters indicate the model and the last three indicate a specific configuration of that model. It’s also seen with various HP computers, although their pattern tends to be a little more difficult.
The “gather” process that MDT uses doesn’t provide a way to do wildcard or “like” queries, but it does provide extensibility to let you define your own property to use instead of “Model” when querying the database. Let me give a “real world” example for the Lenovo case. I can use a CustomSettings.ini like this:
[Settings] Priority=CalculateCustom, MMSettings Properties=CustomModel [CalculateCustom] CustomModel=#Left("%Model%", 4)# [MMSettings] SQLServer=MNiehaus-T61p-7 Instance=SQLExpress Database=MDTDatabase Netlib=DBNMPNTW SQLShare=DeploymentShare$ Table=MakeModelSettings Parameters=Make, CustomModel CustomModel=Model
[Settings] Priority=CalculateCustom, MMSettings Properties=CustomModel
[CalculateCustom] CustomModel=#Left("%Model%", 4)#
[MMSettings] SQLServer=MNiehaus-T61p-7 Instance=SQLExpress Database=MDTDatabase Netlib=DBNMPNTW SQLShare=DeploymentShare$ Table=MakeModelSettings Parameters=Make, CustomModel CustomModel=Model
This defines a new property called “CustomModel”. It includes a rule that has a very simple manipulation: it sets the value to the first four characters of the existing “Model” value, which in the case of my T61p laptop results in a value of “6458”.
I then modified the database query to tell it to use “CustomModel” as a parameter instead of “Model”. If that’s all I did, the query would fail because it would create a SQL statement that specified “WHERE CustomModel = ‘6458’” but that’s not valid since there isn’t a CustomModel column in the database. That’s where the next line comes in:
CustomModel=Model
This says that the property “CustomModel” as we know it locally is called “Model” in the database. As a result, the correct query is generated:
About to issue SQL statement: SELECT * FROM MakeModelSettings WHERE MAKE = 'LENOVO' AND Model = '6458' Successfully queried the database.
That’s all it takes. Now, there would typically be more than just the [MMSettings] section that needs the “CustomModel” updates – you would also want to change [MMPackages], [MMApps], [MMAdmins], and [MMRoles] the same way.
If you need to do a calculation that is more complex than the simple substring that I implemented above, you may need to use a user exit to do the calculation. The end of the exit just needs to set the same “CustomModel” property. The rest of the logic would be the same. So you could use something like this for the exit:
Function UserExit(sType, sWhen, sDetail, bSkip) If sType = "SECTION" and sWhen = "BEFORE" then oLogging.CreateEntry "Calculating custom model string.", LogTypeInfo If UCase(oEnvironment.Item("Make")) = "LENOVO" then oEnvironment.Item("CustomModel") = Left(oEnvironment.Item("Model"), 4) ElseIf Instr(oEnvironment.Item("Model"), "(") > 2 then oEnvironment.Item("CustomModel") = Trim(Left(oEnvironment.Item("Model"), Instr(oEnvironment.Item("Model"), "(") - 2)) Else oEnvironment.Item("CustomModel") = oEnvironment.Item("Model") End if End if UserExit = Success End Function
Function UserExit(sType, sWhen, sDetail, bSkip)
If sType = "SECTION" and sWhen = "BEFORE" then
oLogging.CreateEntry "Calculating custom model string.", LogTypeInfo
If UCase(oEnvironment.Item("Make")) = "LENOVO" then oEnvironment.Item("CustomModel") = Left(oEnvironment.Item("Model"), 4) ElseIf Instr(oEnvironment.Item("Model"), "(") > 2 then oEnvironment.Item("CustomModel") = Trim(Left(oEnvironment.Item("Model"), Instr(oEnvironment.Item("Model"), "(") - 2)) Else oEnvironment.Item("CustomModel") = oEnvironment.Item("Model") End if
End if
UserExit = Success
End Function
Save that as “CustomModelExit.vbs” in the same “Scripts” directory with ZTIGather.wsf, then edit the CustomSettings.ini to specify to run it:
[Settings] Priority=CalculateCustom, MMSettings Properties=CustomModel [CalculateCustom] UserExit=CustomModelExit.vbs [MMSettings] SQLServer=MNiehaus-T61p-7 Instance=SQLExpress Database=MDTDatabase Netlib=DBNMPNTW SQLShare=DeploymentShare$ Table=MakeModelSettings Parameters=Make, CustomModel CustomModel=Model
[CalculateCustom] UserExit=CustomModelExit.vbs
The only change from the previous CustomSettings.ini sample is the [CalculateCustom] section. Now it specifies the run the user exit script. So what exactly does this script do? Well, if it’s a Lenovo machine, it takes the first four characters. If the models string contains a starting parenthesis, “(“, it will chop everything from that point off of the model (e.g. “My Model (Test)” will become “My Model”). In any other case, the script will assign the current model value to the CustomModel property. (That simplifies things somewhat.)
You might need to tweak the script some based on your specific requirements, but the basic setup should work for whatever manipulation you would like to do.
I mentioned before that the boot image creation process used by the Deployment Workbench is significantly enhanced in MDT 2010 Beta 2, but didn’t really talk too much about how the process works behind the scenes. Now, this is template-based, with XML files that specify exactly what should be included in each boot image that we generate:
When you perform the “Update Deployment Share” process, the Deployment Workbench will take these XML files (located in C:\Program Files\Microsoft Deployment Toolkit\Templates), add some additional items to them (e.g. settings you specified on the deployment share properties such as optional components to add, settings like RAMdisk size, etc.), and then use that to build the new boot image. (As mentioned in the previous article, the process is optimized to only do the minimum amount of work – it does this by comparing the new XML file against the one generated the last time the boot image was generated. It then figures out what needs to be done based on the difference between the two.)
So what if you want to add your own files into our boot images? Just modify the template to tell us where to get them and where to put them in the image and the “Update Deployment Share” process will take care of it.
That’s fine for simple additions like adding files, but what if you want to do something more substantial? That’s where exit scripts come in. (I call this the “Johan feature”.) You’ll notice that the existing templates specify a sample exit:
<!-- Exits --> <Exits> <Exit>cscript.exe "%INSTALLDIR%\Samples\UpdateExit.vbs"</Exit> </Exits>
When the “Update Deployment Share” process runs, this exit script will be called multiple times for each phase of the process, allowing you to make customizations to the process. Variables will be passed along so that you know where everything is located, what is currently going on, etc. The phases:
In each of the phases, various environment variables are defined:
The “C:\Program Files\Microsoft Deployment Toolkit\Samples” directory does contain the UpdateExit.vbs script described above, which demonstrates all the variables I described.
There is one bug in MDT 2010 Beta 2 that I have to point out though: the “STAGE” variable is always set to “WIM”, so it’s kind of hard to figure out which phase you are currently in. That’s been fixed for the released version of MDT 2010.
When you perform a Lite Touch deployment, the task sequence runs through to completion, and then you will see a summary wizard that shows you any errors or warnings that may have occurred during the process. That wizard could be skipped by setting “SkipFinalSummary=YES” in CustomSettings.ini. (One behavior worth pointing out: With MDT 2010 Beta 2, if the task sequence fails, the SkipFinalSummary setting will be ignored and the wizard will be shown anyway.)
A common request we received was to provide a mechanism for specifying what should be done after the wizard is completed (or if it is skipped). With MDT 2010 Beta 2, we have provided that through a “FinishAction” variable that you can set in CustomSettings.ini. Valid values include:
If you don’t specify any value, the default is to just exit like was done in MDT 2008. The shutdown, restart, or logoff activities happen after the Lite Touch scripts have cleaned up the machine (copying logs to the network, removing MININT, removing autologon settings, etc.). In the case of restart or logoff, the machine will end up at the logon screen, ready for a user to log on.
There were two main database limitations in MDT 2008 Update 1:
With MDT 2010 Beta 2, we’ve fixed those limitations:
If you are looking for the database node in MDT 2010 Beta 2, you can find it under the deployment share’s “Advanced Configuration” node. That means that each deployment share can have its own database, too.
It seems like an understatement to just say that MDT 2010 now supports PowerShell to automate Deployment Workbench administrative tasks. Really, Deployment Workbench has been completely re-architected – all operations you perform through the UI are turned into PowerShell commands that are executed by the PowerShell engine, providers, and cmdlets. As a result, a significant portion of the Deployment Workbench has been rewritten – this is definitely no small change.
Behind the scenes, there are a few pieces to make this work:
All of these are contained in a single PowerShell snap-in, so before you can use the PowerShell provider yourself you need to load this snap-in. This is pretty easy to do with a single PowerShell command:
Add-PSSnapIn Microsoft.BDD.PSSnapIn
First let’s talk more about the PowerShell provider. In order to use it, you need to create a “PowerShell drive” (see http://technet.microsoft.com/en-us/library/dd315335.aspx for details). This is like mapping a network drive: creating a logical “drive” that is used to navigate through the logical contents of a deployment share. The MDT PowerShell provider doesn’t create any drives by default, so you need to create one or more. This can be done in one of two ways. First, the manual way:
New-PSDrive -Name MyDrive -PSProvider MDTProvider -Root \\server\DeploymentShare$
In this case, the logical drive name assigned will be “MyDrive” (you could use whatever value you like), it is created using the MDT PowerShell provider which is called “MDTProvider” (always), and it points to the deployment share at \\server\DeploymentShare$. Once the drive is created, you can navigate through it and look at the contents.
But first, let’s talk about the second way of creating MDT drives. The Deployment Workbench keeps track of all deployment shares that you opened through the UI. To get the same ones through PowerShell, you can execute a single cmdlet:
Restore-MDTPersistentDrive
You’ll see the names and paths for all restored drives, e.g. “DS001” for the first deployment share \\server\DeploymentShare$.
OK, so now let’s assume you have at least one PowerShell drive, “MyDrive”. To see the top-level folders, try this:
Want to see all the drivers? Try:
dir 'MyDrive:\Out-of-Box Drivers'
Want to create a new folder? Try:
mkdir ‘MyDrive:\Out-of-Box Drivers\New Folder’
Want to see all the deployment share properties? Try:
Get-ItemProperty MyDrive:
Want to update the deployment share (generating boot images)? Try:
Update-MDTDeploymentShare -Path MyDrive:
You can use pretty much any of the standard PowerShell cmdlets for drive providers:
What if you want to create new applications, import drivers, create task sequences, update the deployment share, etc.? That’s where the other MDT cmdlets come in:
The Deployment Workbench does all of its work using the cmdlets listed above. In many cases, the wizards will show you these PowerShell commands, so that you can copy and paste them into your own PowerShell scripts.
With any luck, we’ll post more PowerShell script samples in the coming months.
Version 4.0 of the User State Migration Tool will release with Windows 7. The RC version of it is available in the Windows Automated Installation Kit for Windows 7 RC (http://www.microsoft.com/downloads/details.aspx?FamilyID=60a07e71-0acb-453a-8035-d30ead27ef72&displaylang=en). This has several new features, including one that MDT 2010 takes advantage of: hard-link migration. If you are performing a Lite Touch “refresh” deployment (backing up the user state, clearing the old OS, installing a new OS, reinstalling apps, and restoring the user state), this process can be made significantly faster using hard-link migration, taking minutes instead of hours because it doesn’t actually move any of the data. Instead, it just creates new links to the same existing files in a protected folder (e.g. C:\MININT). When the old OS cleanup process runs later, it deletes the original links but the files remain because there is still another link in the protected folder.
The “estimate” process that is executed in the task sequence recognizes that USMT 4.0 is present. When a refresh is being performed, it will skip the estimate because it knows a hard-link migration can be performed.
If you want to see this process in action, check out Jeremy’s video at http://edge.technet.com/Media/User-State-Migration-with-Windows-7/.
This same process works with ConfigMgr 2007 Beta 2 as well, again with the ZTIUserState estimate process automatically setting the right variables to perform a hard-link migration. (We are investigating some issues with this, so try it out in your lab to make sure you won’t run into these.)
There are lots of other features in USMT 4.0 as well. See http://technet.microsoft.com/en-us/library/dd560752(WS.10).aspx for the full list.
As mentioned previously, MDT 2010 now allows you to create as many folders as you want, in whatever hierarchy you want. Once you have all of these folders, you need a convenient way of selecting one or more that you want to use for various activities. That’s where selection profiles come in: they allow you to select a set of folders to use.
Selection profiles are used for several purposes in the Deployment Workbench and in Lite Touch deployments themselves:
There are several built-in selection profiles, all of which are read-only so they can’t be modified or deleted:
You can create as many additional selection profiles as you want. Just right click on the Selection Profiles node and choose “New Selection Profile”. The wizard will ask for a name and the folders you want to include. You can select as many or as few folders as you wish.
It’s worth pointing out a few other behaviors too:
This should make it easier for you, as you don’t need to worry about editing selection profiles each time you add a new folder or remove an existing one.