Microsoft Management Summit (MMS) is a great place to learn about the great new products and features that Microsoft is making available, especially System Center products. There are a lot of great sessions that I would have loved to have gone to including several for Orchestrator, System Center Ops Manager, Configuration Manager, Server Manager, and PowerShell to name a few. However, there were several sessions that our group put on which we had to prepare for. It always amazes me how much work goes into putting together a presentation especially when one of the pieces required for a key demo gets corrupted and requires you to rebuild everything from scratch.
While at MMS, Chris Adams and I presented Package Conversion Manager (PCM) “BG03 – Converting Your Existing Software Packages into the Configuration Manager 2012 Application Model”. Besides getting sick and presenting with a temperature in the hundreds the presentation went fairly well. Well OK maybe I was just delirious from my temperature. There were several questions asked during the presentation, but the main one seemed to be whether or not we can help with software that is wrapped in a custom installer. I will be answering this question as well as giving a high level overview of Package Conversion Manager in a future blog post. Overall we got some really good feedback. We also met up with a couple of TAP customers who are interested in PCM who also gave us some great insight on how they package their software and how they setup their collections. This really helped us learn how we can build PCM more effectively for customers.
For those TAP customer’s we interfaced with I will be sending you our CTP1 of PCM shortly. For those TAP customers that are interested in PCM, ask your product group representative and we should be able to get our CTP 1 to you. For those that are not TAP customers and who are interested in PCM, we hope to make our CTP 2 available from the Microsoft Connect site as soon as it is available.
Oh, and one more thing: I will continue to post OSD specific content on this blog, but because I will be posting content around Package Conversion Manager I figure I better change up the title to be less OSD specific. Hopefully I can find a good title to fit the blog, but in the meantime I will simply change cravings of OSD out for cravings of System Center.
I have received several emails asking why applications are not showing up in various scenarios even though they have been configured. Depending on the scenario there are a number of reasons why this may occur. In this blog post I will be concentrating on one of the reasons why this may occur.
So you have opened up the designer and have configured the wizard’s configuration file. As part of the configuration you have connected to your site server and added several applications. When you open the wizard in preview mode however the applications don’t show up. Or even worse they show up while in preview mode but they do not show up at times when running through an actual task sequence.
One of the main reasons for this occurring is due to architecture. This can be the architecture of the machine or the architecture of the image that you selected. The OSD Designer and UDI wizard gives you the ability to add either x86 and/or x64 applications. This allows for the scenario of only displaying applications to the end user based on the architecture of the target Operating System. If an application only worked on x86 you would not want to show the application to the end user if they selected an x64 target OS as it would fail when it got to the point of installing the application. Additionally this allows for the scenario where there are different programs which installs x86 compared to x64.
In this blog post lets use the example of an Adobe Reader being configured as shown in the below screenshot:
As you can see the 32 bit properties have been filled out but the x64 properties have not.
Using the above example this Adobe Reader app will only show up when the end user selects an x86 image. If they select an x64 image then this application will never show up in the list. If the program was meant to run on both architectures then simply attach it to both the 32 bit and 64 bit properties as seen below and it should show up if the end user has selects either a 32 bit or 64 bit image from the wizard’s image drop down as the target OS.
If there is a different program for the same app that runs on an x64 architecture then simply attach it.
In this scenario the OSD Admin has disabled the volume page of the wizard and only attached the 32 bit program properties. This is a valid scenario as the admin may only have configured one image in the task sequence and may not want to give the end user a choice of the image or any of the other options from the volume page of the wizard.
In the event that the Wizard doesn’t know what the architecture of the target OS will be, which is the case when the volume page is disabled, it will display apps based on the architecture of the machine. Therefore if your machine is 64 bit and the volume page is disabled, any application that was only configured with 32 bit program properties will not be displayed from the application page of the wizard.
One way to get around this is to simply set the OSDArchitecture task sequence variable to the architecture of the image that was configured as the target OS in the task sequence prior to the wizard loading. Of course this will not help you in the event that you loaded the wizard in preview mode. If this is the case make sure that you have set up your applications properly and if need be, simply enable the volume page prior previewing the wizard and then disable it again after you find it is configured to your liking.
I will explain the second reason that your applications may not display, specifically in preview mode, in a future blog post
In a previous blog post located here we outlined how to create an interactive task sequence experience and detailed how to interact between a system session and a user session. Although it is not our recommended approach, as we would like you to use the tools available, sometimes customization outweighs using an in box solution. So in this blog post I will outline how you can launch your own customized wizard using the same technique we use to launch the UDI wizard.
You can use the same command line that UDI uses in order to launch your customized wizard. Although the UDI wizard has a script wrapper to do a few other things to launch the wizard interactively it follows this simple command line process:
ServiceUI.exe -process:tsprogressui.exe Wizard.exe
In this example ServiceUI will look for which session tsprogressUI.exe is running in so it can display my.exe to it. However, because it was launched from the task sequence it will be running in system context.
If you were to run from the UDI task sequence you would probably want to use the already defined task sequence variables in order to specify the paths of your custom wizard. Of course you must first update your scripts package to include your custom wizard executable.
Here is an example:
%ToolRoot%\ServiceUI.exe -process:tsprogressui.exe %ScriptRoot%\MyCustomWizard.exe
Launching an HTA will be very similar as the process outlined above, but instead ServiceUI.exe must launch mshta.exe which in turn calls your customized HTA. Here is an example:
%ToolRoot%\ServiceUI.exe -process:tsprogressui.exe %SYSTEMROOT%\system32\mshta.exe %ScriptRoot%\MyCustomHTA.hta
I know that I haven't posted in a while, but I have been thinking about it. I have several topics in draft form just waiting to be finished up and posted. In today's blog I will go over the task sequence variables that are read or set based on the selections made from each page in the wizard.
No variables are read or set for this page.
No variables are read or set from the wizard for this page. However, there are some task sequence variables that may be set from some of the preflights being run from the page. An example of this is the variable set from the BitLocker preflight check.
This task sequence variable specifies if BitLocker Drive Encryption is enabled on the target computer by the BitLocker preflight check.
Value
Description
Example
PROTECTED
The target computer has BitLocker Drive Encryption enabled.
OSDBitlockerStatus=PROTECTED
Does not exist
If the target computer does not have BitLocker Drive Encryption enabled, then the task sequence variable does not exist.
The computer name assigned to the target computer
Computer Name
The computer name to assign to the target computer
OSDComputerName=%_SMSTSMachineName%
Specifies the name of the domain to which the target computer will be joined if the computer is configured to be a domain member.
Domain Name
OSDDomainName=domain01
Specifies the name of the OU in the domain to which the target computer account will be created when the computer joins a domain.
OU Name
The name of the OU in the domain in which the computer account will be created.
OSDDomainOUName=OU=Workstations,DC=MyDomain,DC=MyCorp,DC=MyForest,DC=COM
Specifies the name of the workgroup to which the target computer will be joined if the computer is configured to be a workgroup member.
Workgroup Name
The name of the workgroup to which the target computer will be joined.
OSDWorkgroupName=WORKGROUP01
Specifies whether the target computer joins a domain or a workgroup.
0
Specifies that the target computer will join a domain. Additionally if this variable is set to this value then the domain/workgroup radio button will be set to domain.
OSDNetworkJoinType=0
1
Specifies that the target computer will join a workgroup. Additionally if this variable is set to this value then the domain/workgroup radio button will be set to workgroup.
OSDNetworkJoinType=1
Specifies the domain-based account used to join the target computer to the domain specified in the OSDDomainName task sequence variable. This task sequence variable is necessary if the target computer will be joined to a domain.
Account Name
The name of the account used to join the target computer to the domain in the format of domain\account.
OSDJoinAccount=domain\account
Specifies the password for the domain-based account used to join the target computer to the domain specified in the OSDJoinAccount task sequence variable. This task sequence variable is necessary if the target computer will be joined to a domain.
password
Specifies the password for the Administrator local built-in account on the target computer.
The password of the Administrator local built-in account on the target computer.
OSDLocalAdminPassword=password
This task sequence variable specifies a list of domain-based accounts or local accounts to be added to the Administrators local built-in group on the target computer.
domain\account_name1; computer\account_name2
The format of the accounts to be made members of the Administrators group on the target computer in the format of domain\account and separated by semicolons, where domain can be the name of an Active Directory domain or the target computer name.
OSDAddAdmin=domain\user01;Win7-01\LocalUser01
The default language to be used with the target operating system. If not specified, the language configured in the image being deployed will be used.
UI_language
The default language for the operating system on the target computer
UILanguage=en-us
The user locale to be used with the target operating system. If not specified, the user locale configured in the image being deployed will be used.
user_locale
The locale for the user on the target computer. For:
· Windows Server 2003, the value is specified as a hexadecimal value (0409:00000409).
· Windows Server 2008, the value is specified as a text value (en-us).
UserLocale=fr-CA
Default system locale used for the operating system.
locale
The default locale of the operating system
SystemLocale=0409:00000409
Keyboard locale to be used in the deployed operating system.
keyboardLocale
An additional keyboard locale to be made available in the deployed operating system
KeyboardLocale=0409:00000409
The default time zone
Time Zone
The default time zone that will be set for the deployed operating system
Specifies the index number of the target operating system in a WIM file.
index number
The index number of the target, which starts with an index number of 1 for the first operating system in the WIM file.
Specifies the processor architecture of the target operating system selected for deployment.
x86
The target operating system is a 32-bit operating system.
OSDAchitecture=x86
amd64
The target operating system is a 64-bit operating system.
OSDAchitecture=amd64
Specifies the disk volume where the target operating system will be deployed.
disk volume
The disk volume designation
OSDTargetDrive=C:
Specifies the folder in which the Windows operating system is currently installed on the target computer.
windows directory
The directory in which the Windows operating system is currently installed from which the user state will be captured from.
OSDWinPEWinDir=C:\Windows
Specifies whether the target disk partition should be formatted.
YES
The target disk partition will be formatted.
OSDDiskPart=YES
NO
The target disk partition will not be formatted.
OSDDiskPart=NO
Specifies which applications should be selected by default on the Install Software page of the Operating System Deployment (OSD) Setup Wizard.
list of app ids
A semicolon-delimited list of application to be selected by default on the Install Software page of the Operating System Deployment (OSD) Setup Wizard; each application is represented by an application ID and separated by a semicolon. The application ID is derived from the Id attribute of each application in the UDIWizard_Config.xml file. In the following excerpt from a UDIWizard_Config.xml file, the Office 2007 SP2 application has an Id attribute of 1:
<Application DisplayName="Office 2007 SP2" State="Disabled" Id="1">
NOTE: This variable can be read in but when the wizard exits it will set the task sequence variables in a manner which can be read by the task sequence.
OSDApplicationList=2;3
These variables will be set based on which applications are selected when the wizard exits and what the base variable name is set to.
PKGID:Program Name
The base variable name is configurable from the designer for the wizard. The name used must match the base variable name used in your task sequence on the Install Software Step.
The number of applications which can be installed range from 1 to 999 from this single step. By default the base variable name used with UDI is Packages so the avaible variables which can be set are: Packages001 - Pacakges999.
Packages001=SMS0000C:Office Setup
No variables are set from this page. However, as this is the last page in the wizard when the Finish button is selected then the selections for each page will be set as task sequence variables.
Specifies if the user cancelled the Operating System Deployment (OSD) Setup Wizard. The wizard can be cancelled from any page in the wizard.
True
The user cancelled the Operating System Deployment (OSD) Setup Wizard.
OSDSetupWizCancelled=True
If the wizard is not cancelled, then the task sequence variable does not exist.
The long awaited release of MDT 2010 Update 1 is finally here. After making several fixes over the Beta version, MDT 2010 Update 1 released earlier this week.
To find out what is different between Modena and UDI, and when to use UDI, LTI, or ZTI please see the Beta release link here.
To find out more about MDT 2010 Update 1, please the visit the TechNet Library or the MDT 2010 TechCenter. In addition to these links you can download MDT 2010 Update 1 from here.
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
Thanks,
MPSD Engineering
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")
Main
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)
End Sub
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
/L:"%usmtlogs%\Scanstate.log"
/progress:"%usmtlogs%\Scanprogress.log"
/ListFiles:"%usmtlogs%\ListFiles.txt"
"%usmtbits%\loadstate.exe" "%usmtsafe%" /hardlink /nocompress /lac /c /v:13
/i:"%usmtconf%\MigDocs.xml" /i:"%usmtconf%\SelfHostApps.xml"
/i:"%usmtbits%\MigApp.xml" /L:"%usmtlogs%\loadstate.log"
/progress:"%usmtlogs%\loadprogress.log"
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
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"
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
--"
TSEnv("USMT_ScanTime") =
USMT_ScanTime
TSEnv("USMT_ScanSize") =
USMT_ScanSize
TSEnv("USMT_LoadTime") =
USMT_LoadTime
TSEnv("USMT_LoadSize") =
USMT_LoadSize
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) )
End IF
Next
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 namespace("\\\\.\\root\\CIMV2")
#pragma deleteclass("HWINV_OSD_Details", NOFAIL)
[DYNPROPS]
class HWINV_OSD_Details
{
[key] string KeyName = "";
string TSType;
string TSVersion;
string OSDImagePackageId;
string OSDBitlockerStatus;
string OldComputerName;
string OSDComputerName;
string OSDJoinAccount;
string OSDStartTime;
string OSDEndTime;
string OSDInstallLP;
string OSDGUID;
string USMT_ScanTime;
string USMT_ScanSize;
string USMT_LoadTime;
string USMT_LoadSize;
};
instance of HWINV_OSD_Details
KeyName = "HWINV_OSD_Details";
[PropertyContext("local|HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\MPSD\\OSD|TSType"),
Dynamic, Provider("RegPropProv")] TSType;
[PropertyContext("local|HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\MPSD\\OSD|TSVersion"),
Dynamic, Provider("RegPropProv")] TSVersion;
[PropertyContext("local|HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\MPSD\\OSD|OSDImagePackageId"),
Dynamic, Provider("RegPropProv")] OSDImagePackageId;
[PropertyContext("local|HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\MPSD\\OSD|OSDBitlockerStatus"),
Dynamic, Provider("RegPropProv")] OSDBitlockerStatus;
[PropertyContext("local|HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\MPSD\\OSD|OldComputerName"),
Dynamic, Provider("RegPropProv")] OldComputerName;
[PropertyContext("local|HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\MPSD\\OSD|OSDComputerName"),
Dynamic, Provider("RegPropProv")] OSDComputerName;
[PropertyContext("local|HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\MPSD\\OSD|OSDJoinAccount"),
Dynamic, Provider("RegPropProv")] OSDJoinAccount;
[PropertyContext("local|HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\MPSD\\OSD|OSDStartTime"),
Dynamic, Provider("RegPropProv")] OSDStartTime;
[PropertyContext("local|HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\MPSD\\OSD|OSDEndTime"),
Dynamic, Provider("RegPropProv")] OSDEndTime;
[PropertyContext("local|HKEY_LOCAL_MACHINE\\Software\\Microsoft\\MPSD\\OSD|OSDInstallLP"),
Dynamic, Provider("RegPropProv")] OSDInstallLP;
[PropertyContext("local|HKEY_LOCAL_MACHINE\\Software\\Microsoft\\MPSD\\OSD|OSDGUID"),
Dynamic, Provider("RegPropProv")] OSDGUID;
[PropertyContext("local|HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\MPSD\\OSD|USMT_ScanTime"),
Dynamic, Provider("RegPropProv")] USMT_ScanTime;
[PropertyContext("local|HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\MPSD\\OSD|USMT_ScanSize"),
Dynamic, Provider("RegPropProv")] USMT_ScanSize;
[PropertyContext("local|HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\MPSD\\OSD|USMT_LoadTime"),
Dynamic, Provider("RegPropProv")] USMT_LoadTime;
[PropertyContext("local|HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\MPSD\\OSD|USMT_LoadSize"),
Dynamic, Provider("RegPropProv")] USMT_LoadSize;
SMS_DEF.MOF snippet
#pragma namespace("\\\\.\\root\\CIMV2\\SMS")
[ SMS_Report (TRUE),
SMS_Group_Name ("HWINV_OSD_Details"),
SMS_Class_ID ("MICROSOFT|HWINV_OSD_Details|1.0") ]
class HWINV_OSD_Details : SMS_Class_Template
[SMS_Report (TRUE), key ]
string KeyName;
[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;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices; // Namespace for Import DLL
namespace HideSetupWindow
class Program
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.
In Consolidating Your Task Sequence Part 1: How to Combine WIM images into one I discussed how you can combine your images into one. This blog talks about how to apply the appropriate index from a task sequence when a WIM file has multiple indexes, such as Win7 x86 and Win7 amd64.
Why would I consolidate my images into one:
The simple answer is to use the built in task sequence variable called OSDImageIndex to apply the right image. This variable must be set with the appropriate number that corresponds to the index of the image you are trying to apply from a WIM. The UDI Wizard Designer which will be available as part of UDI, formally known as Modena, will be available when MDT 2010 update 1 Beta ships. However, an older version of the designer, along with other Modena tools, is available now from our connect program. The designer allows an administrator to create the XML configurations that are run with the OSD Setup Wizard also available with Modena and soon to be with UDI. So an administrator can simply set up his WIM image as was outlined in Consolidating Your Task Sequence Part 1: How to Combine WIM images into one and then use the designer to set the image index to the corresponding number. He will also need to give each index a friendly name and set the appropriate architecture for each of the indexes. An example of which can be seen in the below screenshot.
After the administrator has created and saved his XML configuration from the Designer, he can use it as part of the deployment by making sure that OSDSetupWizard.exe points to the XML file using the “/xml:” switch. As part of the deployment, based on the image that an end user selects from the drop down the OSDImageIndex variable will be set with the number that corresponds to the image that was selected. In the screenshot below this would be index 2 if the administrator set it as is seen above.
When the task sequence gets to the “Apply Operating System Image” step it will use the OSDImageIndex variable to determine which index to apply out of an image. Because the variable is set, the task sequence will disregard whatever image index is selected on this task sequence step and apply the index that was set in the OSDImageIndex variable instead.
For more information about this and related variables please check out this page: http://technet.microsoft.com/en-us/library/dd252753.aspx.
Consolidating Your Task Sequence Part 1: How to Combine WIM images into one
If you have multiple images that you deploy but would like to reduce the amount of operation overhead in maintaining task sequences, consolidating your task sequences into one task sequence should be considered. For example if you have a task sequence that deploys an x86 image and a different task sequence to deploy the amd64 version of the image, combining these images into one WIM with multiple indexes and combining your task sequences into one task sequence is something that should be considered.
As a rule of thumb images can be combined by using the following steps:
If there are additional images you can continue by mounting ImageC etc. and appending them to ImageA.
Now that we have gone over the procedure at a high level lets take a look at a specific example and the command needed to combine images. The purpose of this blog is not to talk about how images are captured so lets say that we have captured an image called Win7x86.wim and another image called Win7amd64.wim and we would like to combine these images. As a best practice the x86 image should be the first index in a combined image (perhaps this is just personal choice, but for the remainder of this blog it will be outlined in this way).
To avoid confusion on which image is which lets start out by changing the name and description for the first image (or index) and the name of the actual file before appending additional images. Lets start by renaming the file to Win7Combined.wim. Now lets change the information in the image using the following example:
imagex /info Win7Combined.WIM 1 "Win7(x86)" "Windows 7 x86"
Using this command the first index in the WIM has had its name changed to “Win7(x86)” and its description to "Windows 7 x86".
The change can be verified by using imagex /info Win7Combined.WIM
So now we will need to mount our Win7Amd64.wim and append it to the Win7Combined.wim. This will be done using the /apply switch, which will actually extract all of the files to the directory specified. Keep in mind that whatever directory you apply the image to will need to be empty. Follow this example to mount the image:
imagex /apply "Win7Amd64.wim” 1 C:\Mount
Where 1 is the index of the image and C:\Mount is the location where the image will be applied. Of course the image can be applied to any directory as long as it is empty.
Now the image is ready to be appended to the first image that was renamed. Use the following example to append the images:
Imagex /append C:\Mount "Win7Combined.WIM" "Win7(AMD64)" "Windows 7 AMD64"
This will append the mounted image to the x86 image that we modified at the beginning. Additionally we have set the name to "Win7(AMD64)" and the description to "Windows 7 AMD64" of the appended image.
Now that the images have been combined imageX can be used with the /info switch to see that the image count is now 2.
Note: You can also use DISM.exe for this process also
This Blog post was created by Michael Schmidt.
Controlling the look and feel throughout OSD a very important part of creating a good user experience. Not only is the out-of-box experience a bit bland, it’s unfamiliar and confusing to someone who’s never experienced OSD before. Our goal in this article is to outline how to spice up the end-to-end deployment experience.
At a glance, a user should be able to tell:
Should the deployment go awry, these questions become even more important. In one glance, without looking at logs, anyone viewing the screen can answer questions such as:
With BGInfo, the available information to display is nearly limitless; you have complete control over what details are visible and important to your organization.
A mockup of what might be used to accomplished this goal is shown below:
All this is possible through the use of BGInfo. With this utility, the background screen can be changed at any point in your Task Sequence.
In the mockup provided, the following practices were taken:
So, in the example given, 5 bitmaps were created. Thus, BGInfo will be called 5 times within our Task Sequence. Each bitmap represents the active “Phase” in an “On” position, and all other “Phases” in an “Off” position.
Since our deployment consists of 5 phases, we’ll need 5 different bitmaps. In addition to 5 different bitmaps, we actually need 5 BGInfo configuration files. BGInfo configuration files store rendering information used to display the background; these files are passed to BGInfo as parameters.
To create a screen, open BGInfo and:
Defining the background image to use, color, and positioning:
Defining what computer information is displayed, and where to position it:
Create all 5 pages in this manner, and save each BGInfo session. After completing these steps, the final list of files will look something like this:
Assuming all the required files exist in one directory, a method for calling the appropriate “Step” is necessary. This can be accomplished through a batch file containing the following:
In this manner, your Task Sequence would simply reference the package and call the batch file with a Step number:
To maintain the look and feel across the entire deployment, there are three areas where adjusting the background image is important for consistency:
When initially starting up in Windows PE, a default built-in background image is displayed. Until your Task Sequence begins and the background batch file runs, a user will see whatever background ships in Windows PE.
Apply your own background by opening up the SCCM console, locating your boot image, and modifying its properties. Look for the “Windows PE Background” field:
After applying and booting into it the new OS (after the “Setup Windows and ConfigMgr” step), an animated black background will appear for the duration of your Task Sequence. Windows Setup overlays a full-screen window named “FirstUXWnd”, displaying the text “Setup is preparing your computer for first use”. Until the Task Sequence has completed in its entirety, this window will be seen and the custom background will not.
Task Sequence background after booting into the new OS:
Assuming you’ve customized the first half of your Task Sequence to show a snazzy look/feel, you’ll probably want to persist this. Especially if your Task Sequence contains a large number of post-OS-install tasks, such as application installs.
One simple and safe workaround is to hide this window. Since we know the window title, we can simply search for it and send it a “hide window” message. However, this requires creating a small application to perform the hide.
Creating this application isn’t too difficult. An example of the API calls necessary to perform this is given below. Using either .NET or native C++, this is relatively simple to create.
Once completed, run this binary from your Task Sequence immediately after the “Windows Setup and ConfigMgr” step.
Update! A complete source-code sample is available here.
You now completely control the deployment look and feel, end-to-end.
This blog post was created by Michael Schmidt.
At Microsoft, we have the unique challenge of having to build a OSD experience that includes providing a great user experience prior to deployment of a new OS. In our case, we had the challenge of figuring out how we could do this considering that task sequence runs in Session0 and many of our users would never get this pretty user experience.
In the interest of helping others who have this same goal - bettering the user experience of OSD – we wanted to cover launching an interactive process from the Task Sequence (TS). No binaries are provided; this post only journals a high-level overview of creating a C++ binary to launch an interactive process.
A similar idea with source is available from The Deployment Guys.
Assuming the user interface/wizard is pre-built in the form of a standard binary (.exe), a launcher is necessary. Shown below is an example of the launcher concept, and how it might be used.
Since processes launched under WinPE are visible, this launcher provides value only when run from an existing OS. Two of the primary modes for operating a TS are:
With a custom launcher, a UI could be spawned from any place in your Task Sequence. It could be used to:
Another point worth mentioning is that a native launcher has no dependency on the .NET Framework. All API calls covered will run on Windows XP and higher. Building a launcher after this manner grants deployment flexibility, in relation to target OS and required runtimes.
When running a Task Sequence within an existing Operating System (OS), all TS work is performed in SYSTEM context. As a result, all user interface (UI) wizardry you might inject wouldn’t be visible to the user (Windows Vista+). To quickly cover this (emphasis added):
Impact of Session 0 Isolation on Services and Drivers in Windows Vista “The Microsoft Windows Vista™ operating system mitigates this security risk by isolating services in Session 0 and making Session 0 noninteractive. In Windows Vista, only system processes and services run in Session 0. The first user logs on to Session 1, and subsequent users log on to subsequent sessions. This means that services never run in the same session as users’ applications and are therefore protected from attacks that originate in application code.”
Take note of the following points:
Our goal is to launch a process from SYSTEM context into a session where our user interacts. Since TS execution is performed in Session 0 (non-interactive), we need to locate an alternative, interactive session which the user is running under. How can one tell which Session ID the user is operating under? One useful API to determine this might be:
In most cases, WTSGetActiveConsoleSessionID is sufficient to retrieve the working session. Unfortunately, while this session provides the physical console session ID, problems arise when multiple users are logged in (or when our target user is connected over Remote Desktop/Terminal Services). A more appropriate function for our purpose is:
Now, only one TS can execute at a time. When the TS launches, a process is spawned by the TS to show progress; this process is “tsprogressui.exe”. OSD opens this process from SYSTEM context into the active user’s session, which is precisely what we’re attempting to do. Thus, in our launcher we simply search for the OSD-spawned “tsprogressui.exe” process. By searching for this process and calling ProcessIdToSessionId against it, we can determine the session ID our UI should spawn in.
Searching processes can be accomplished through the following API calls:
An example of this is provided by MSDN; using this example, we can extract the session ID by:
Now for the tricky part. I defer source examples for this next section to the wide world of the web, but will overview on the idea. Most important is the CreateProcessAsUser API. Using this function, it becomes possible to launch your UI from the Task Sequence in SYSTEM context, into the user’s session. When this is accomplished, your UI will be visible/interactive.
The difficulty in making this call is the preparation. Numerous parameters must be created and pre-populated prior to making the call, and this is where the trouble lies.
An Access Token, representing the user we wish to execute under, is required for CreateProcessAsUser. Before launching a process under the user’s session, this token must be created/duplicated. To perform this, we extract and duplicate an Access Token from the existing user’s Winlogon session.
Once a handle to Winlogon is obtained, an Access Token can then be extracted. First, a template containing the privileges we require is necessary (LUID type); this will be used when creating/duplicating our Access Token (TOKEN_PRIVILEGES object).
While many other parameters are required, they’re much simpler to generate. Creating the Access Token is the tricky part; MSDN documentation and other code samples suitably cover the rest. However, when launching from a TS you’ll likely need to wait for the process to end, and want to know the resulting exit code. Launch, wait, and process the return code in this order:
This is all it takes… a little bit of code and a little bit of work and you can give a “new” face to OSD like never before thought of. To wrap up the order presented for creating a launcher:
A few small tips to consider when developing, testing, or troubleshooting.
Working between SYSTEM and USER context can be difficult and complex. PsExec is invaluable for troubleshooting; this utility can open a process in SYSTEM context, allowing the ability to test your binary. To open a SYSTEM context command-line, run the following from an elevated command window:
It’s useful to see what tasks are executing under which Session ID. Add the “Session ID” column to Task Manager:
For those of you who do not know me I was the feature PM of the product formally known as Modena. I am recently getting back from MMS where I helped my boss, Chris Adams, with his demo during the MDT 2010 Update 1 + ConfigMgr 2007 OSD: Even More "Better Together" session, and have decided to start my own blog. Yes, I know "more better" isn't exactly the best English, but I didn't come up with the title. This session talked to the new enhancements that would be available with 2010 update 1 and demonstrated the features that will be available with the release.
During this session it was announced that Modena is now being called UDI and would be included in MDT 2010 Update 1 due to be released soon. The OSD Setup Wizard, Designer, and OSD Results will all be included in the release and were demonstrated as part of the session. I would like to set the record straight for anyone who did see this session. I did not tell Chris to use a remote desktop connection to his machine and then demo turning off the network card of his VMJ. I thought he would be directly connected to his VM.
As part of the integration a lot of changes were made to the Modena task sequence in order to make it similar to the MDT task sequence templates. Additionally several of the Modena scripts were either merged into MDT by enhancing an existing MDT script or were excluded altogether as an existing MDT script already contained the needed functionality.
As to the coded features available with UDI, the majority of the enhancements were done to the designer. The timeline of the previous release of the designer did not allow for much of the validation functionality we would have liked to include. Because of this the majority of this work includes better error handling and validation checking with the designer. Just one example is that in the previous version of the designer it allowed adding in as many of the same image indexes as you wanted. So you could add image index “1” a hundred times, but your image would only include one image index “1”. If this scenario occurs in the next release of the designer it will give you a popup informing you that the index is already in use. This is just one of many validation enhancements that have been made to the designer.
As UDI is further integrated and released I look forward to blogging about it, its features and enhancements in the future.