This blog post is meant to quickly explain some of the things that you should know when using UDI. I will not go into depth on solutions for each of the scenarios that I have listed here, but will create additional posts for those items that need to be explained in more detail.
When using Modena and you started from WinPE we did not make an assumption that you want to blow away all partitions. However, the template has changed now that it is moved into MDT and is called UDI. Be forewarned that with MDT when you start from WinPE it is thought of as a new computer. So to cover this if you select to backup your user state rather than format, it will leave your partitions alone. If you select format, all bets are off and disk 0 with be repartitioned to only have 1 partition. As this post is an attempt to try and get information that you should know out there as quickly as possible, I will try to cover additional information from a different post on how to set it up if you only want the target drive to be formatted rather than repartitioning.
If you have local user accounts and have backed up user state you will run into a problem in which your user states will fail to restore. This is because users will not get created as a password for setting up these accounts has not been specified out of the box. There are a number of options when dealing with this problem.
When an x64 boot image is used for operating system deployments, the status background bitmap will not be displayed in Windows PE environment. Currently there isn’t a x64 version of BGInfo.exe, which is used to display the backgrounds. Keep in mind you can use an x86 boot image for applying either an x86 or x64 image rather than using the “applying an image from original source bits” option. If you are doing the latter then you will need to use a boot image with the same architecture as the image that you are applying.
For installing language packs, you need to configure the list of language packs in UDI Wizard Designer and for each of the language packs an Install Language Packs Online or Offline task sequence step will need to be added in the UDI Task Sequence pointing to the Language Pack package. Additionally you will want to setup conditions for each of these steps so that the appropriate language will be applied only when it was selected by the end user. I will try to go more in depth on this subject in a later post.
This occurs when the time date format is different than the time date format at the end of the deployment. For example if you start from WinPE and it is in a US time date format and then you install a German language pack and set your default system locale to this date and currency format this will occur. This is something that we are looking at fixing for the RTW version of UDI.
A WIM image of your drive will currently be captured even if you have selected to format. To avoid capturing a WIM of a drive that has been already formatted simply add an OSDDiskPart not equals true condition on the backup step and it will save some time as well as disk space. When set in this manner a backup of the drive will only be taken when the format option is not selected. If you never want to capture a WIM image of the drive simply disable the backup step.
You must install the designer on a machine that has the Configuration Manager Console. Certain console dlls are used when connecting to a site server in order to pull down a list of packages. Additionally in order to use the UDI Wizard Designer, the Web Service Installer, and OSD Results you must have .Net Framework 3.5 SP1 installed. When 3.5 SP1 is not installed the designer will through a warning message stating that it is required. When the web service runs it also lists its requirements. As OSD Results is a runtime executable used in your deployments it will simply not run prior to the logon screen. You might ask what if I have .Net Framework 4.0 installed. It wont’ work by itself. You must install 3.5 SP1 which can be installed with 4.0 in parallel.
As is in the release notes for the Web Service: If you receive a 404.3 when browsing to the web service, this is typically due to WCF mime type not being registered correctly. To register the WCF mime type on the web server, browse to: %Windir%\Microsoft.NET\Framework\v3.0\Windows Communication Foundation. From an elevated command prompt run ServiceModelReg.exe –i. This should register the mime type for the .svc extension, required by the web service.
There are a few scenarios around Bitlocker that should be discussed. First the the one change between Modena and UDI is that the Enable Bitlocker step has been disabled in the default UDI template. Because users may want to setup Bitlocker with a pin and the OSD Setup Wizard doesn’t prompt for a pin, or anything for Bitlocker for that matter, we decided that it would be best just to disable the step. If you would like to setup Bitlocker without a pin you can simple enable the Bitlocker step in the task sequence and then change any of the settings provided from this step.
If you only want to run if Bitlocker was enabled previously you can add a condition in addition to the existing conditions on the Enable Bitlocker step so it will only run if OSDBitlockerStatus equals protected. This variable is set when the Check Drive Encryption(OSDBitlockerState.vbs) runs from with the OSD Setup Wizard. Because this preflight check is only executed when the OSD Setup Wizard is run from within Vista or Win7, this variable will only be set when starting from these operating systems. For example if you set it up in this way and you started from WinPE you would never have Bitlocker re-enabled as this variable would never be set.
When starting from WinPE two of the scenarios that we needed to cover were offline state capture and bare metal. In many instances as was the case with MDT previously, if you start from WinPE it is considered a new computer and formats the drive. Since we support offline user state capture you can’t just boot to WinPE, kick off your task sequence, and format the drive as you might unintentionally blow away user state. So to cover this scenario we set the first step in the task sequence template called “Prompt before partitioning disk” to run a script contained in an MDT boot image. Then we added several condition to the group containing this step, one of which is a query to check to see if you have any partitions. If you don’t have any partitions the step will run and prompt you whether you would like to partition and format you disk. If a user selects yes then it will format the machine. If a user selects no then it will cancel out of the task sequence much in the same way that the UDI wizard does when you select cancel. Again this is only available if you have created a new boot image with MDT 2010 Update 1 Beta.
There were 3 configuration files available with Modena. However, with UDI this has been stripped down to one configuration file. This decision was made as really the only difference between the configuration files were the preflight checks executed from those configuration files. Now there is a wrapper around the Setup Wizard that will determine which OS the task sequence is running in at the time and then strip out the appropriate preflight checks for that environment and save that information into a new XML. The script will then execute the setup wizard with the newly created XML.
The time may come when you want to add in your own preflight checks that only runs in a specific environment or you may want to run multiple configurations for other reasons and run them based on a condition from your task sequence. For this you may ask, “can I simply run the wizard with the /xml switch as I did in Modena?” It will run, but there are certain things that the wrapper does after the wizard exits such as converting the string value for the variable used to add in additional users into the local administrators group into a format that is consumed by existing MDTs scripts. Because of this I would not suggest you use the /xml switch when running. Instead run the script with the /definition switch and point it to the appropriate configuration file such as the following: cscript.exe "%DeployRoot%\Scripts\UDIWizard.wsf" /definition:..\..\scripts\<configuration XML>. This will allow you to run the setup wizard, point it to your XML, and still have the functionality of the UDIWizard script. One thing to note if you specify the /definition switch the UDIWizard.wsf does not strip out any preflight checks. So if you put together a customized XML you would need to make sure to customize it based on the environment that it will be run in by only including the preflight checks that run in that environment.
The long awaited release of MDT 2010 Update 1 Beta is finally here. We have been working hard to integrate Modena into MDT, now known as UDI. Today is the day when users can finally get their hands on it. What is UDI, you might ask. It stands for User Driven Installation. For those that are not familiar with Modena, UDI gives the end user the ability to interact with Configuration Manager Operating System Deployment (OSD), which is not available with out of the box OSD. In addition to the OSD Setup Wizard which is displayed to the end user, UDI comes with the UDI Wizard Designer which allows an administrator to customize the end user’s Wizard experience. Additionally UDI comes with a number of preflight scripts, a web service for storing your application master configuration, and OSD Results (an executable that shows a summary of the deployment such as how long it took and whether your selected applications were successfully installed or not).
Don’t worry, if you are new to Modena or UDI we will be talking about all of these components in later blog posts to better familiarize you with what is available with UDI. For those that are familiar to Modena we will cover some of the differences between Modena and UDI in this blog post. In addition to UDI there are a number of new features and bug fixes that available with MDT 2010 Update 1 Beta outside of UDI. However, as I was the feature PM for Modena and a PM for integrating Modena into MDT under the name UDI, I will be concentrating on UDI specific content for this post.
At a high level I will try to cover what the difference is between Modena and UDI. Modena was a tool we created internally to meet our deployment needs which we thought other users of Configuration Manager may also find useful. Because of this we made it available through several releases to the Microsoft Connect site. Although at a low level there are quite a few changes between Modena from the previous release and UDI available with the MDT Update 1 Beta release, for this blog post I will try to stick to the major changes between the two:
UDI comes with one configuration file while Modena came with three. The three Modena configuration files where used based off of the environment the OSD Setup Wizard was running from. There was one configuration file for XP, one for WinPE, and one used while started from either Vista or Windows 7. The only difference between these configuration files were the preflight checks that were run in each environment. If these checks were run from an environment that they were not intended to run from they may return an error and an end user may not be able to move forward from the preflight page of the wizard. However, because UDI now has a wrapper around the OSD Setup Wizard which checks which environment the wizard is running in and based on that environment strips out the unneeded preflight checks, we have been able to get the OSD Setup Wizard down to 1 configuration file. What happens if you want multiple configuration files? I will go over that later in a later post.
With Modena, after you installed the Modena components you would need to copy the given bits to their source directory and setup all of the Configuration Manager packages manually. After this was done you would need to import the task sequence into your Configuration Manager console and associate the appropriate package to each of the steps missing a package. One of the nice things about integrating with MDT is when you want to use the UDI template you simply need to right click on the task sequence node of the console and select “Create Microsoft Deployment Task Sequence”.
Now select “User Driven Installation Task Sequence” from among the templates:
Now you will be walked through a wizard for creating your task sequence. As part of this process the wizard will ask you if you have existing install image package, SCCM Client Package, boot image package, MDT toolkit package, USMT package, and MDT settings package. If you do not have existing packages then you can specify information such as a name and the package source in order to have the package created for you as part of the process (including copying the bits to the source directory). This will happen after confirming your selections from the wizard. Don’t forget that once the packages are created you still must associate these packages to at least one distribution point to be usable as part of the task sequence. Now if you would like to customize your task sequence you just need to edit it from the task sequence node and make your changes. This makes for a better administrator experience as you will not have to edit the task sequence and then associate each of the requisite packages to each of the steps requiring those packages.
As nice as it was to have a UI for modifying and creating your configuration files there were a number of things that we would have liked to have done for the previous release of the Designer, but there simply wasn’t enough time as is normally the case. We added a lot of validation checks around the designer. For example when you add an image index to the designer it now validates whether that image index was already added and gives you a prompt. This is just one of many examples of the validation that has been added to the Designer. There is no longer a Blogs page, but when we RTW we plan to add help links into the designer where the blogs page was. Overall the designer still has the same look and feel as it did previously just with a bit more logic behind it.
The task sequence between Modena and UDI has completely changed. It is now a merge between the previously released Modena task sequence and a standard MDT Client Task Sequence. The task sequence is now structured in such a way to handle MDTs Refresh and New Computer scenarios for example, but still includes a master group, called execute task sequence, a group for cancelling the wizard, and a failover group for gathering logs. There are many differences in-between that I plan to blog about in future posts.
With MDT there used to be two different deployment methods: LTI (Lite Touch Installation) and ZTI (Zero Touch Installation). Now with UDI (User Driven Installation) you may wonder in which scenario should I use each of these deployment methods. The chart deploy walks you through when each method should be used.
Keep following this blog as I will be posting new information about UDI and OSD.
Join the MDT Update 1 Beta. (Live ID required.)
To see the official blog post for the release click here
Learn more about MDT 2010 and its components by visiting the MDT site on TechNet.
The following blog post was created prior to Modena releasing as UDI. Although the designer shown is not the released version the video points are still applicable.
Applications can be one of the most difficult things to administer, but when setup correctly can also be one of the most robust and user friendly portions of a deployment.
In today’s getting started blog post we will be covering how to setup applications along with the configuration options available for applications. If you have seen the Getting Started video on an Introduction to the OSD Designer then you should have an overall understanding on how applications are configured. However, we will be delving in depth on several areas of configuring applications which will hopefully help you get the most out of your deployment user experience around applications.
As part of the Modena installer the OSD Designer will be made available along with generic configuration files. Today’s video will walk you through using the OSD Designer and one of the generic configuration files in order to configure applications. This will include setting up groups, covering how packages are listed from a configuration manager server, how the application discovery preflight is tied into the application configuration, as well as how a base variable is configured. Additionally this video will be covering how application dependencies, exclusions, mappings, and WHQL queries are configured for the Modena OSD Setup Wizard. So lets get started setting up applications…
Download this Video
For those times when you need to find out what a variable is set to while running a task sequence, you can run a simple script along with the variable name that you would like to check the value for. As long as the task sequence environment is available and the variable’s value is set to something other blank, it should return the value.
Dim sTSVar, sParameters, oTSEnv, Wsh Set oTSEnv = CreateObject("Microsoft.SMS.TSEnvironment") Set Wsh = CreateObject("Wscript.Shell")
Sub Main() On Error Resume Next
If trim(Wscript.Arguments.Item(0)) <> "" Then DisplayVariables Wscript.Arguments.Item(0) Else Wscript.echo "No TS variables were passed for the script-" & Wscript.ScriptFullName End If If Err.number <> 0 then Wscript.echo "Error Writing the variable." & Err.Description End If End Sub
Sub DisplayVariables(sParameters) Wscript.Echo oTSEnv(sParameters)
Let’s say you named your script readtsvar.vbs. While the task sequence was running you could hit F8 to open a command window and simple run the following:
cscript readtsvar.vbs OSDComputerName
This would return whatever the computer name variable is currently set to.
If you are using ConfigMgr to deploy Operating systems, and leveraging USMT (User State Migration Tool) for User State migration, you would be very much interested in finding out answers for the following questions.
Hopefully you have used USMT 4.0 with its hard link capabilities to speed things up in contrast with copying data over the network onto a remote share. Regardless of the method you had chosen for your USMT implementation, trying to capture the USMT usage statistics isn’t as simple as it sounds for all systems across your environment.
In this post, we will share the process we chose to use at Microsoft for collecting USMT statistics.
At a high level, the process of collecting USMT usage statistics can be broken down as below:
Except for the last step of collecting inventory data using ConfigMgr, the first 3 steps are basically task sequence steps within the OS deployment task sequence.
This step is where we will parse USMT logs to get the required details that will be reported back to ConfigMgr site. To start with we need to know the location of the logs where the USMT executables are configured to write. Based on our configuration, the progress logs are written to %usmtlogs%\Scanprogress.log & %usmtlogs%\loadprogress.log as indicated by the command lines below.
"%usmtbits%\scanstate.exe" "%usmtsafe%" /o /c /hardlink /nocompress
/efs:hardlink /i:"%usmtconf%\MigDocs.xml" /i:"%usmtconf%\SelfHostApps.xml"
/i:"%usmtbits%\MigApp.xml" /offlinewindir:"%2" /localonly /uel:45 /v:13
"%usmtbits%\loadstate.exe" "%usmtsafe%" /hardlink /nocompress /lac /c /v:13
After locating the log files, now let’s see where the information about ‘how long it took to capture’ and the ‘size of data captured’ is hidden. For simplicity sake, we will consider only scanstate information; however the same logic is applicable for loadstate as well.
If you search for a string “, totalSizeinMBToTransfer,” in ScanProgress.log, you will locate a line that looks something like the one below. The value next to the string (16605.29) is the size of data that is captured as part of scanstate in MB. Now, it is just a matter of reading that value alone using any scripting method, and storing this value as a Task Sequence variable.
11 Sep 2009, 23:34:52 +05:30, 00:02:23, totalSizeInMBToTransfer, 16605.29
11 Sep 2009, 23:34:52 +05:30, 00:02:23, totalSizeInMBToTransfer, 16605.29
The same logic goes for finding the ‘time it took to capture the user state’, except that, this time you will be looking for a string “, errorCode,” in the same ScanProgress.log. It is usually the last line in the log with an error code of 0 if all went well. Again, using any scripting method you need to pick up the value just before the string “, errorCode”, which is 00:06:34 in the sample below.
11 Sep 2009, 23:39:02 +05:30, 00:06:34, errorCode, 0, numberOfIgnoredErrors, 0, message, "Successful run"
11 Sep 2009, 23:39:02 +05:30, 00:06:34, errorCode, 0, numberOfIgnoredErrors, 0, message, "Successful run"
Before we get into, how we store the values into Task Sequence variables - why we store these data in Task Sequence variables and then move them again into registry deserves some attention.
Even though USMT data is the focus of this post, there is lots of other information that we capture which is relevant to OS deployment process. To name a few - information like OSD Start & End times, Old & New computer Names, and OSD Image Package ID are captured that are already either part of default or custom Task Sequence Variables in our deployment process. Hence, to keep the complete tracking of data in cohesion, we chose to populate USMT data also in Task Sequence Variables, and at a later state all the Task Sequence Variables’ values are collectively written to registry. So, in short, you could technically skip this step, and directly populate the USMT values into registry and jump to the last step of ‘Use ConfigMgr to report data’.
Now, let’s come back to ‘how we store values’ into Task Sequence Variables. This is a relatively easy step with only few lines of code that can do the trick. Assuming the USMT_ScanTime, USMT_ScanSize, USMT_LoadTime & USMT_LoadSize are already populated from the earlier step; it can be directly assigned to the variables after instantiating the TSEnv object as shown below.
SET TSEnv = CreateObject("Microsoft.SMS.TSEnvironment")
wscript.echo "--------------- Updating Task Sequence Variables
The entire script is available from our Connect site and instructions for joining that program can be found here.
With the required data in the Task Sequence variables, we are now onto the stage where we need to move them into Registry keys; which will be later collected via ConfigMgr inventory process.
Reading Task Sequence environment variables are very much similar to the method, which we saw in the earlier step. Basically, you start with instantiating Task Sequence Environment, and looping through the variables you can read them and perform any action that is required. In the snippet below, you will notice that after reading the variables, a MatchMaker function is used to compare the value against a mapping of values which need to be included or excluded.
Dim oTSE : SET oTSE = CreateObject("Microsoft.SMS.TSEnvironment")
For Each tV in oTSE.GetVariables()
IF (MatchMaker( tV, incArray ) = TRUE) Then
IF (MatchMaker( tV, excArray ) = FALSE ) Then
Call BrandValue( tV, oTSE(tV) )
If it meets the inclusion criteria and is not part of the Exclusion criteria, a function by name BrandValue is called; which will populate the registry key as seen below. Based on prior evaluation of OS architecture (64/32 bit system), appropriate reg.exe is used and the registry location is chosen.
' //////////////////////////////////////////////////// Brand a name and value to registry
Sub BrandValue( theName, theValue )
Dim retVal : retVal = 0
Dim runCmd : runCmd = REGBRAND & " ADD " & REGBRANDPATH & " /F /V " & theName & " /T REG_SZ /D """ & theValue & """"
Wscript.Echo " Branding : [" & runCmd & "]"
retVal = oWSH.Run( runCMD, 0, True )
Wscript.Echo " Result : [" & retVal & "]"
This step is typically the last step in our task sequence to ensure we capture all the Task Sequence Variables onto registry for inventory purposes. With the data now in registry keys, we are now ready to collect that data using ConfigMgr.
Finally, after all the pre-requisite work of populating the required data in the registry of machines, we will see what needs to happen next to get that data into the ConfigMgr database for easy retrieval in the form of reports.
As with any inventory data collection using MOF in ConfigMgr, retrieval of USMT values from Registry Key here is no different. However for the sake of completeness, we will see how this is actually done within ConfigMgr. There are set of MOF files named Configuration.MOF and SMS_DEF.MOF, which control what data is collected as part of inventory agent by ConfigMgr clients. Configuration.MOF instructs ConfigMgr clients to create WMI class, and SMS_DEF.mof tells ConfigMgr clients what to pick up from the WMI class and report to ConfigMgr site up the hierarchy.
The snippets available below, pretty much do the job of collecting inventory information and reporting them to ConfigMgr site. You would need to append these snippets into the respective MOF files at the site server. Of course, after tweaking to meet your needs and testing it.
As mentioned earlier, our approach of data collection is more than just USMT and hence you see those additional lines which are not related to USMT.
#pragma deleteclass("HWINV_OSD_Details", NOFAIL)
[key] string KeyName = "";
instance of HWINV_OSD_Details
KeyName = "HWINV_OSD_Details";
Dynamic, Provider("RegPropProv")] TSType;
Dynamic, Provider("RegPropProv")] TSVersion;
Dynamic, Provider("RegPropProv")] OSDImagePackageId;
Dynamic, Provider("RegPropProv")] OSDBitlockerStatus;
Dynamic, Provider("RegPropProv")] OldComputerName;
Dynamic, Provider("RegPropProv")] OSDComputerName;
Dynamic, Provider("RegPropProv")] OSDJoinAccount;
Dynamic, Provider("RegPropProv")] OSDStartTime;
Dynamic, Provider("RegPropProv")] OSDEndTime;
Dynamic, Provider("RegPropProv")] OSDInstallLP;
Dynamic, Provider("RegPropProv")] OSDGUID;
Dynamic, Provider("RegPropProv")] USMT_ScanTime;
Dynamic, Provider("RegPropProv")] USMT_ScanSize;
Dynamic, Provider("RegPropProv")] USMT_LoadTime;
Dynamic, Provider("RegPropProv")] USMT_LoadSize;
[ SMS_Report (TRUE),
SMS_Class_ID ("MICROSOFT|HWINV_OSD_Details|1.0") ]
class HWINV_OSD_Details : SMS_Class_Template
[SMS_Report (TRUE), key ]
[SMS_Report (TRUE) ]
After the site server had a chance to create new inventory policies for clients; clients during its next inventory cycle will send the data up to its ConfigMgr site server. Once the data is processed by the data loader thread (one of the threads of SMS_Executive service), the data finally shows up in SQL database. Based on the class name we used, the below query will show data in ConfigMgr DB.
1: SELECT * FROM V_GS_HWINV_OSD_Details
To summarize what we have seen so far - We went through the process of parsing the USMT logs for specific strings to identify the values we need to collect. After that is done, based on our implementation approach, we populated those values into Task Sequence variable and then to registry. Finally, using standard inventory collection process of ConfigMgr we saw how the MOF needs to be updated to see the data in ConfigMgr database and hence reports.
We hope this was helpful in identifying the hidden information of USMT usage statistics using few simple scripts as Task Sequence steps and the standard inventory process of ConfigMgr.
In this post the basics for finding and hiding a window will be shown in Visual Studio 2008 (C#). As previously mentioned in Snazzy OSD status with BGInfo, hiding the Windows 7 Setup window will be demonstrated.
First, create a simple Console Application under the C# tree.
Next, copy and paste the code sample below.
using System.Runtime.InteropServices; // Namespace for Import DLL
static void Main(string args)
// | Find Window
int hwnd = WinAPI.FindWindow(null, "FirstUXWnd");
Console.WriteLine("FindWindow API Result: " + hwnd.ToString());
// | Hide Window : 0 = Hide, 1 = Show
if (hwnd != 0) WinAPI.ShowWindow(hwnd, 0);
internal static class WinAPI
// FindWindow : http://msdn.microsoft.com/en-us/library/ms633499.aspx
[DllImport("user32.dll", SetLastError = true)]
internal static extern int FindWindow(string lpClassName, string lpWindowName);
// Show Window : http://msdn.microsoft.com/en-us/library/ms633548.aspx
internal static extern int ShowWindow(int hwnd, int nCmdShow);
// NOTE: Any of the following will work...
//int hwnd = WinAPI.FindWindow("FirstUXWndClass", null);
//int hwnd = WinAPI.FindWindow("FirstUXWndClass", "FirstUXWnd");
//int hwnd = WinAPI.FindWindow(null, "FirstUXWnd");
Finally, compile the application.
Use the code sample below to hide an instance of Notepad. Two points worth mentioning:
Parameter 1 is the Class Name. Parameter 2 is the Window Name. Searching on either (or both) parameter is possible:
/* Sample 1 */ int hwnd = WinAPI.FindWindow("Notepad", null);
/* Sample 2 */ int hwnd = WinAPI.FindWindow(null, "Untitled - Notepad");
/* Sample 3 */ int hwnd = WinAPI.FindWindow("Notepad", "Untitled - Notepad
In parting, a very accommodating utility for learning and working with this type of window manipulation is Winspector.
This blog post was originally created by Michael Schmidt.