Welcome to TechNet Blogs Sign in | Join | Help

Keeping An Eye On USMT Progress

I recently did a project where all users had around 25Gb (don’t ask!) of data that had to be migrated with the USMT during the OS deployment.  Because of the sheer volume of data, the USMT phases of the project took an extremely long time to complete, and because no on-screen feedback is given of the progress, the customer would often think that something had hung, so they often cancelled the deployment; only to find that it was indeed running correctly.  In order to stop them doing this, I wrote a very simple VBS script that showed the current progress of the USMT.  It works by simply parsing the progress file, looking for the percentage progress of the process.

tracker

I thought I would publish it here, because when I showed it to some colleagues they asked for a copy as they thought it would be useful to use during the lab phases of MDT projects.

It consists simply of a VBS file that requires the path of the USMT log file to be passed as a parameter.  The script creates a small HTML window that then displays a single line showing the progress of the USMT as a percentage.  You can either launch the script by hand or add it to the task sequence.  To add this to the task sequence, simple add the following “Run Command Line" action before the USMT capture or restore actions (or both):

cmd.exe /c “start /MIN cscript.exe Z:\Scripts\CUSTOM_USMT_Tracker.vbs C:\MININT\SMSOSD\OSDLOGS\USMTCapture.prg”

cmd.exe /c “start /MIN cscript.exe Z:\Scripts\CUSTOM_USMT_Tracker.vbs C:\MININT\SMSOSD\OSDLOGS\USMTRestore.prg”

Why the two commands lines?  Well, the first one is to show the progress of the capture phase of the USMT, and the second is to show the progress of the restore phase.  Also, I should point out that the command is launched in this way because MDT needs to launch the command, and then move on.  If you don't have the cmd.exe /c "start" part at the beginning then MDT will launch the script and wait for it to finish (which is never) and the USMT commands will never fire.  You may also have noticed that I had to put the drive letter in the command path, this is because the variable %SCRIPTROOT% is not available with this usage.

The screenshot below shows what it looks like in action.

desktop

Be warned though, this script does consume quite a few CPU cycles because it is probably not the most efficient routine; it was really a proof-of-concept thing that I wrote in order to show that everything was running as expected.  When I wrote it I was running it on dual core desktop computers and it didn’t seem to noticeable affect the deployment time.

Attached to this post is the script file.

This post was contributed by Daniel Oxley a consultant with Microsoft Consulting Services Spain

Disclaimer: The information on this site is provided "AS IS" with no warranties, confers no rights, and is not supported by the authors or Microsoft Corporation. Use of included script samples are subject to the terms specified in the Terms of Use.

Posted by Daniel Oxley | 0 Comments
Filed under: , , ,

Attachment(s): USMT_Tracker.vbs

Updated Hardware Detection Script

Or… How Not to Create Boolean Properties in an MDT Script

I my posts about Windows XP Tablet PC Edition 2005, I provided a script that could be used for detecting Tablet PC digitizers or an set of devices by Plug & Play ID (ZTI-DetectHardwareExit.vbs).  My customer has been using this script for months in Windows XP deployments without issue to determine if the target PC was a Tablet PC and apply the correct OS image. This was until the customer tried the first European deployment in Italy.

When they first tried the XP deployment it failed on the Apply Driver Package step.  We found that no OS had been applied and the Apply Driver Package was trying to work against the Windows 2000 OS still on the disk.  After troubleshooting we discovered that the way I was setting the IsTablet value (the return value of the DetectDevices function) in the script was the cause.  MDT Properties are strings, so to convert the Boolean value in my script to a string I simply used the VBScript CStr function.  What I failed to realize is that CStr will do a language specific conversion of the Boolean to a string.  So when the language was set to Italian, the IsTablet property was being set to either “Vero” or “Falso” instead of “True” or “False”.  Since our Apply Operating System Image steps in the Windows XP Task Sequences were conditioned on whether IsTablet equals “True” or “False”, no OS image was being applied.

Once I realized what was happening, I looked to see how ZTIGather.wsf was doing the Boolean to string conversions.  Lo and behold, the MDT Team had, of course, made accommodation for this.  ZTIGather.wsf has a ConvertBooleanToString function that performs “a Cstr operation manually to prevent localization from converting True/False to non-english values”.  Once I changed the script to use the ConvertBooleanToString function, it worked correctly with the Italian language machines.

I have place an updated version of ZTI-DetectHardwareExit.vbs in the download for the previous post.  This version also has some additional changes based on another issue we encountered.  The installations in Italy were done using DVD media.  The ISO files were copied over the customer’s WAN.  Some of the ISO images did not copy properly.  On some of the DVDs, the Microsoft.BDD.PnpEnum.exe utility was corrupted.  The caused the utility to simply do nothing.  Since the text file generated using this tool was now blank instead of containing the needed XML data, my script was failing.  So I’ve included additional error checking and when an error occurs the return value will be the string “Error”.  This was done to allow the ability to optionally fail the Task Sequence when an error is encountered in ZTI-DetectHardwareExit.vbs.  My customer wanted the Task Sequence to fail if the IsTablet properly was not properly set because either no OS or the wrong OS would be applied.

The CustomSettings.ini entries for enabling this failure on error should look like this (changes for this in red):

[Settings]
Priority=IsTabletCheck, ByTabletType, Default
Properties=MyCustomProperty, TabletPnpIds, IsTablet, XPTabletProductKey

[IsTabletCheck]
TabletPnpIds=ACPI\WACF004,ACPI\WACF008,ACPI\MAI3310,ACPI\FUJ02E5
UserExit=ZTI-DetectHardwareExit.vbs
IsTablet=#DetectDevices("%TabletPnpIds%")#

[ByTabletType]
Subsection=Tablet-%IsTablet%

[Tablet-True]
XPTabletProductKey=XPTabletProductKey=AAAAA-BBBBB-CCCCC-DDDDD-EEEEE
OSInstall=Y

[Tablet-False]
OSInstall=Y

[Tablet-Error]
OSInstall=N

[Default]

When OSInstall=N, the step in the Task Sequence that runs ZTIValidate.wsf will exit with failure.

Disclaimer: The information on this site is provided "AS IS" with no warranties, confers no rights, and is not supported by the authors or Microsoft Corporation. Use of included script samples are subject to the terms specified in the Terms of Use.

This post was contributed by Michael Murgolo, a Senior Consultant with Microsoft Services - U.S. East Region.

Installing Applications Using Active Directory Group Membership

Mike recently posted on how to take an MDT action based on group membership in Active Directory.  At the same time, I was working on something quite similar but using a different approach, so I thought I’d blog it here to offer an alternative method to the one Mike describes; I’ll leave it up to you to decide which one to use!

With this solution you can dynamically install applications during a LiteTouch deployment based on the membership of Active Directory groups, this means that each computer deployment can be uniquely customised, without the need for complex scripting or advanced infrastructure.  All that is required is this blog post, a group created in Active Directory for every application that will be dynamically installed, and all computer accounts pre-created in the domain and added to the relevant application groups.

The process is as follows:

  1. Define global variables
  2. Define application specific variable
  3. Query Active Directory for group membership
  4. If computer is a member of the group, install application.  If not, move to next action.
  5. Clean up variables used

The five steps above can be looped through as many times as required, but steps two to four are required for each application installation.  I created a demo task sequence that implements the working solution, shown below, to help visualise the sequence:

1

As is is not clear from the screenshot above, each step is explained below (note that you can name the actions as you wish, but the task sequence variables must adhere to the specifications here otherwise the script will fail.  As you can see, inside the AppInstall group, there are five actions and a task sequence group for each dynamic application install.  The group “Install – App1” consists of the following (these actions are identical for all subsequent application groups):

  • INSTALLAPP – a task sequence variable, the value set is FALSE.
  • DomUser – a task sequence variable called DOMUSER, the value set is the fully qualified domain name of user in the target domain, i.e. where the computer account exists and also where the group has been created.
  • DomPassword – a task sequence variable called DOMPASSWORD, the value set is the password of the previous mentioned account - stored in clear text.
  • FQDNDC – a task sequence variable called FQDNDC, the value set is the fully qualified domain name of a domain controller in the target domain.
  • NetbiosDC – a task sequence variable called NETBIOSDC, the value set is the NetBIOS name of the previous domain controller.
  • Group – App1 – a task sequence variable called ADGROUP that specifies the fully qualified domain name of the application group to check .
  • Query LDAP – App1 – a “Run Command Line” action that launches the script CUSTOM_AppInstall.wsf using CSCRIPT.exe
  • Install Application – App1 – A standard “Install Application” task sequence action, configured to install App1.  It has a condition set to only launch if the value of INSTALLAPP is TRUE.
  • CleanUp – App1 – resets the value of the task sequence variable INSTALLAPP to FALSE.

To implement this solution in your task sequence, you should first copy the WSF script file into the .\Distribution\Scripts folder, and then create all the task sequence actions as described.  In the attached .ZIP file to this post are screenshots of each action as well as the script file; these should help you configure the actions correctly.  There are a couple of points you should be aware of:

  • The password for the user is stored in the XML file for the task sequence in clear text.  Consequently, do not use any user account that has any rights on the domain, this account should be as limited as possible.  It would not be hard to edit the script file so that you could include encryption, or obfuscation in order to improve security.  I’ll try to post an update of this script in the future in order to include this feature.  You might be able to recycle some of the code from this post if you wish to do it yourself.
  • The script does not log any entries in any of the MDT log files, this can make debugging a bit tricky.  The script has been tested and I have it working onsite with a customer, the only problems you are likely to have are related to incorrect FQDNs specified.  I find the use of ADSIEdit on a domain controller useful to find out the correct FQDN of the user or a group.  Again, the future version of this script will include logging functionality.
  • The solution differs to Mike’s in that it works during the task sequence for computers that are not members of the target domain, or are logged on as a non-domain user account (such as the local administrator account used during the LTI install).  This is the reason for having to include a user account and password in the task sequence, binding is needed with a domain controller in order to run an LDAP query.  Also, Mike’s solution uses the CustomSettings.ini file which means that it can be shared between various task sequences, what I detail here is task sequence specific.  I chose this approach though because I wanted to use a more graphical approach for configuring the variables.
  • All the steps inside the group “Install – App1” are required for every dynamic application installation.  The five previous steps to this group only need to be added to the task sequence once.
  • You can include system reboots in the sequence.
  • This post describes using an LDAP query to dynamically install an application, but it could be easily adapted for any other task sequence action :-)

This post was contributed by Daniel Oxley a consultant with Microsoft Services Spain

Disclaimer: The information on this site is provided "AS IS" with no warranties, confers no rights, and is not supported by the authors or Microsoft Corporation. Use of included script samples are subject to the terms specified in the Terms of Use.

Posted by Daniel Oxley | 4 Comments

Attachment(s): Files.zip

Setting AD Computer Object MDT Properties

Monday, June 22, 2009 Update – Fellow Deployment Guy Daniel Oxley pointed out to me that this is much more useful if you can pass in an optional username and password.  So I have modified the post and the script to allow that.  Please note the changes in the function parameters to accommodate this.

------------------------------------------------------------------------

It has come up a few times where someone has requested taking actions in a Task Sequence based on the values of attributes on the computer object for the computer in Active Directory, like the computer’s OU or whether the computer is a member of an Active Directory Group.  So I created an MDT User Exit script to set properties based on such attributes.

This User Exit script, ComputerADAttributesExit.vbs, has three main functions.  Each can be used independently:

  • The SetComputerADProperties function will set some or all of the following properties: ComputerDN, ComputerDomainShortName, ComputerDomainDNSName, ComputerForestDNSName, ComputerSiteName, and ComputerOU.  It’s doing it with calls inside the function like oEnvironment.Item("ComputerDN") = strComputerDN.  The variable ComputerADProperties (shown below) set in CustomSettings.ini is really a throw away (not needed).
  • The SetComputerGroupsList function will create a ComputerGroups list item which will contain the distinguishName of each group to which the computer object belongs.  This is similar to SetComputerADProperties in that the list item is created in the function code.
  • The TestComputerGroup function will return True if the computer is a direct member of the AD group specified in sGroupDN.  Otherwise the return value will be False.  Using this function calls SetComputerGroupsList.  In this case the property like InGroup_GroupName shown below is being set directly in CustomSettings.ini like a standard User Exit property assignment.

Below is a sample CustomSettings.ini show the use of all three:

[Settings]
Priority=ADAttributes, Default
Properties=MyCustomProperty, ComputerADProperties, ComputerGroupsList, InGroup_GroupName

[ADAttributes]
UserExit=ComputerADAttributesExit.vbs
ComputerADProperties=#SetComputerADProperties("username","password")#
ComputerGroupsList=#SetComputerGroupsList("username","password")#
InGroup_GroupName=#TestComputerGroup("CN=GroupName,OU=OUName,DC=Contoso,DC=com","username","password")#

If using a username and password, the username should be of the form: domain\userid.  If you want to use variables for the username and password, they can be used as well.  For example, if you want to use the MDT DomainAdmin variables in ComputerADProperties it would look like this:

ComputerADProperties=#SetComputerADProperties("%DomainAdminDomain%\%DomainAdmin%","%DomainAdminPassword%")#

For using the ConfigMgr Network Access Account it would look like this:

ComputerADProperties=#SetComputerADProperties("%_SMSTSReserved1%","%_SMSTSReserved2%")#

To not use the username and password (current context), pass those parameters as blank:

ComputerADProperties=#SetComputerADProperties("","")#

The properties set by the User Exit script may then be used as conditions in the Task Sequence.

Disclaimer: The information on this site is provided "AS IS" with no warranties, confers no rights, and is not supported by the authors or Microsoft Corporation. Use of included script samples are subject to the terms specified in the Terms of Use.

This post was contributed by Michael Murgolo, a Senior Consultant with Microsoft Services - U.S. East Region.

Windows 7 and BitLocker command Line

So as Windows 7 accelerates to being released to manufacture and we start to get involved in engagements to deploy it I thought I might take a quick look at some changes to BitLocker and how they might help or hinder deployments.

One thing that customers regularly need to do on machines is update the BIOS. Each vendor has their own tools to do this – some have better automation support than others. However they all have one thing in common - if BitLocker is enabled it will detect the BIOS change and prompt the user for their recovery password at restart.

In Windows 7 we now have the ability to suspend BitLocker and then re-enable it. This enables the BIOS to be updated without having to first decrypt the drive or have the user input their password post upgrade.

We can use the BDE command line tool to mange this

Manage-bde.exe –protectors –disable c:

Manage-bde.exe –protectors –enable c:

The –pause option is to suspend encryption of a drive being encrypted.

Remember that while deploying a system it is best to place the BitLocker enablement command at the end of the task sequence – this is now the default in MDT 2010. Placing the enable command at the start will significantly increase the deployment time.

 

Disclaimer: The information on this site is provided "AS IS" with no warranties, confers no rights, and is not supported by the authors or Microsoft Corporation. Use of included script samples are subject to the terms specified in the Terms of Use.

This post was contributed by Richard Trusson, a Senior Consultant with Microsoft Consulting Services - U.K.

Windows 7 and BitLocker to Go

Here is the second of my posts on BitLocker under Windows 7. While not strictly deployment focused I found these points of interest. We all tend to use USB disks for moving data around and securing these is becoming more important. For example how many people have a deployment point on their USB stick that might have user names and passwords in clear text?

BitLocker to Go and legacy versions of Windows

When using BitLocker to Go you can encrypt removable drives with NTFS, but you won’t be able to read them on a down level OS i.e. Windows XP or Windows Vista. However if you encrypt a FAT (or exFAT, FAT32) formatted drive, you will see the BitLocker to Go Reader when you plug it into a down level machine, which will allow read access to your files.

When considering the usage of BitLocker to Go it’s worth noting that you can configure whether or not the BitLocker to Go Reader is included on the removable drive when you encrypt it using Group Policy – Run GPEdit > Computer Configuration > Administrative Templates > Windows Components > BitLocker Drive Encryption > Removable Drives > Allow access to BitLocker-protected removable data drives from earlier versions of Windows.

BitLocker to Go, Certificates and Smart Cards

If anyone has tried out Bitlocker to Go you will have seen the option to encrypt an external disk using your smart card. However not all certificates are suitable for this use.

A certificate is considered valid for BitLocker to Go if the following conditions are met for Key Usage:

No KU is present

KU is present and contains one of the following keyEncipherment bits:

CERT_DATA_ENCIPHERMENT_KEY_USAGE

CERT_KEY_AGREEMENT_KEY_USAGE

CERT_KEY_ENCIPHERMENT_KEY_USAGE

A certificate is considered valid for BitLocker to Go if the following conditions are met for Extended Key Usage:

No EKU is present

EKU is present and contains BitLocker™ OID

EKU is set to anyExtendedKeyUsage

NOTE: The BitLocker OID is configurable in group policy

 

Disclaimer: The information on this site is provided "AS IS" with no warranties, confers no rights, and is not supported by the authors or Microsoft Corporation. Use of included script samples are subject to the terms specified in the Terms of Use.

This post was contributed by Richard Trusson, a Senior Consultant with Microsoft Consulting Services - U.K.

Encoding Command Shell Scripts

On an internal discussion group, the question can up as to whether you could compile or encode a CMD script to prevent casual viewing of the code, similar to what the Script Encoder does for Windows Script Host scripts.  So for fun I decided to see if I could do it.  Here is what I came up with.  (Important Note:  What is shown in this post is simple obfuscation of the code, not encryption.  Do not use any of the techniques in this post to protect sensitive information like user names and password.  They can be fairly easily decoded.)

There is no way built into the operating system to compile or encode command shell scripts.  My first thought was to embed the CMD code as a string or strings in a VBScript that when executed would write the CMD code out to a file in the %Temp% folder, execute it, then delete it.  You could then use the Script Encoder to encode the script.  However, putting the contents of a CMD script into VBScript strings would involve a lot of tedious string concatenation, escaping double quotes, etc.  The I remembered that if construct you script as a Windows Script Host file (.wsf file), you can place multiline strings without modification into a <resource> element.  You can then use the GetResource function to place the contents of the element into a variable.  Below is a sample WSF file that has two lines of CMD script code in the CmdScript <resource> element.  The VBScript code reads the contents of this element, writes it out to a temporary file, runs it, then deletes the temporary file.

<job id="EmbeddedCmd">

    <resource id="CmdScript">
        dir /s "c:\Test" > "C:\Temp\test.txt"
        wmic os get LocalDateTime /value >> "C:\Temp\test.txt"
    </resource>

    <script language="VBScript">
        ' intWindowStyle for WshShell.Run
        Const WINDOW_STYLE_HIDE = 0
        Const WINDOW_STYLE_ACTIVATE_DISPLAY = 1
        Const WINDOW_STYLE_ACTIVATE_MINIMIZE = 2
        Const WINDOW_STYLE_ACTIVATE_MAXIMIZE = 3
        Const WINDOW_STYLE_RECENT = 4
        Const WINDOW_STYLE_ACTIVATE_CURRENT = 5
        Const WINDOW_STYLE_MINIMIZE_ACTIVATE_NEXT = 6
        Const WINDOW_STYLE_MINIMIZE = 7
        Const WINDOW_STYLE_CURRENT = 8
        Const WINDOW_STYLE_ACTIVATE_RESTORE = 9
        Const WINDOW_STYLE_FROM_PARENT = 10

        Set fso = CreateObject("Scripting.FileSystemObject")
        set WshShell = WScript.CreateObject("WScript.Shell")

        tempDir = WshShell.ExpandEnvironmentStrings("%Temp%")
        cdmFilePath = tempDir & "\testfile.cmd"

        cmdScriptCode=getResource("CmdScript")

        Set f = fso.CreateTextFile(cdmFilePath, True)
        f.Write cmdScriptCode
        f.Close

        WshShell.Run "cmd /c """ & cdmFilePath & """", WINDOW_STYLE_ACTIVATE_DISPLAY, True

        fso.DeleteFile cdmFilePath
    </script>

</job>

So this seemed to be all that I needed and I would just encode this with the Script Encoder.  (The script would exist in unencoded form on the disk while it’s executing, but I could see no way to avoid this.)  Unfortunately, it wasn’t that simple.  The Script Encoder predates the introduction of WSF files and does not understand the XML format of the file.  The tool can only encode actual VBScript or JScript code.  So to get it to encode a WSF you have to tell the Script Encoder that the file is an HTML file and it will encode the <script> elements.  The <resource> elements will be left in clear text.

I thought I was stuck until I remembered a blog post by Lee Holmes of the Windows PowerShell team found here.  He Base64 encoded that part of the PowerShell script he wanted to hide it from casual viewing.  I figured I could do the same.  I could Base64 encode the CMD script text and place it in a <resource> element and place a function to decode it in the <script> element.  Then after using the Script Encoder both elements would be encoded.  And this has an advantage over Lee’s script in that the code used to decode the text we really wanted to hide would also be encoded.

Attached are the scripts I put together to try this out:

  • Base64Functions.vbs should contain the functions to encode and decode text to and from Base64.  I did not have my own functions for doing this so I used the ones found here and here to test this.  The copy of Base64Functions.vbs included in the Zip does not contain these functions, since I did not want to redistribute this code without permission.  You will have copy the Base64Encode and Base64Decode functions from the web pages and paste them into Base64Functions.vbs yourself.  You can use other functions that do Base64 conversions as well as long as the function names and signatures match those used in my scripts.  For example, here are functions that use MSXML to do the conversions.  You can also use a different encoding algorithm if you want, like ROT13 for example, but you will have to edit the scripts to use those functions instead.
  • CmdInWsfTemplate.wsf is the template that I use to construct the final script.  It has text markers that I replace to inject the encoded CMD script and the Base64 functions. 
  • EncodeCmdInWsf.cmd is the script the you run on the command line to start the encoding.  It runs EncodeCmdInWsf.wsf to create the target WSF file and then runs the Script Encoder to encode the <script> element.  The syntax is:

        EncodeCmdInWsf.cmd "<path to the CMD script>"
  • EncodeCmdInWsf.wsf is the script that does most of the work.  It read the contents of CmdInWsfTemplate.wsf, Base64Functions.vbs, and the CMD script into variables.  It then encodes the CMD script text, replaces the text markers with the encoded CMD script text and the Base64 functions, and writes out the resulting WSF file with the same base name as the CMD script (e.g. Test.cmd is tranformed into Test.wsf).
  • You will need to install the Script Encoder and copy screnc.exe from its installation folder into the folder with the other scripts.

The resulting script looks something like this (the <script> element is truncated due to column width).:

<job id="EmbeddedCmd">

<resource id="CmdResource">

ZGlyIC9zICJjOlxUZXN0IiA+ICJDOlxUZW1wXHRlc3QudHh0Ig0Kd21pYyBvcyBnZXQgTG9jYWxEYXRlVGltZSAvdmFsdWUgPj4gIkM6XFRlbXBcdGVzdC50eHQiDQo=

</resource>

<script language="VBScript.Encode">#@~^ChUAAA==@#@&P@#@&B,kxDbUNKhjYHVn~6WD,    /4?tssR"E    @#@&ZGUkY~&Hf}mj:5S3m_q92,x,!@#@&ZKx/DPq(1Gr    {UKeJA  .....</script>

</job>

I did this mainly as a fun intellectual exercise and to help a colleague.  I have not tested it beyond what you see here.  As with anything else posted to this blog site, use at your own risk.

Disclaimer: The information on this site is provided "AS IS" with no warranties, confers no rights, and is not supported by the authors or Microsoft Corporation. Use of included script samples are subject to the terms specified in the Terms of Use.

This post was contributed by Michael Murgolo, a Senior Consultant with Microsoft Services - U.S. East Region.

Posted by DeploymentGuys | 0 Comments

Attachment(s): EncodeCmdInWsf.zip

Setting the Time Zone using Windows PowerShell

A few year back a customer of mine was setting the time zone on their computers by directly modifying registry entries.  Since the supported way to do this was to use the SetTimeZoneInformation Win32 API, I created a utility in Visual Basic 6 to allow the customer to set the time zone on their Windows computers from the command line.

Later on, Windows XP included a built-in method to do this using control.exe with a command like:

Control.exe TIMEDATE.CPL,,/Z Pacific Standard Time

where the value after /Z is from the Std or Display values under the time zone subkey of the registry key HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones.

Unfortunately, the control.exe method no longer works on Windows Vista.  When I tried my old VB6 utility on Vista I discovered it no longer worked either.  After asking about it on an internal discussion group, I was informed that my old utility did not work for several reasons.

First, a new privilege (SeTimeZonePrivilege) was created for Windows Vista so that standard users could now change the time zone.  The Date and Time control panel enables this privilege when you use it to change the time zone.  However, custom programs have to enable this privilege programmatically.  Using the AdjustTokenPrivileges Win32 API is one way to do this.  The second reason was that Windows Vista has a new API to set the time zone – SetDynamicTimeZoneInformation.  This API allows control over whether the system uses Dynamic Daylight Savings Time (daylight savings transition dates that change from year to year).  The old API still works but will set the Dynamic Daylight Savings Time setting incorrectly.  It is also recommended that the time zone name parameters for SetDynamicTimeZoneInformation are set from the MUI_Std and MUI_Dlt values from the time zone Registry subkey. To translate these values into the proper language specific string requires using either the RegLoadMUIString or SHLoadIndirectString API.

So I updated my VB6 utility and it now works fine on Windows Vista and higher.  I thought about sharing this version publically but then I decided it would be better if I could demonstrate doing this with a modern language, preferably a scripting language.  Since the Windows Script Host has no mechanism for using Windows API calls, I could not use that.  Luckily there is a newer Windows scripting language that is capable of doing this (albeit indirectly).  That language is Windows PowerShell.

PowerShell itself cannot call Win32 APIs directly.  However, it can use the power of the .NET Framework to do this.  PowerShell can use .NET objects directly using the new-object cmdlet as show here.  However, to call Win32 APIs you have to write some C# code and either create a cmdlet or compile it on the fly from the script.  Since I did not want to have to compiled assemblies as part of this solution I chose the latter.  In PowerShell v1 this can be done with functions like Compile-Csharp found here.  (Note that in the upcoming v2 release there is an Add-Type cmdlet for this.)  Using PINVOKE (Platform Invoke) to call Win32 APIs in C# can be tricky so I’ve provided a few references in case you want to try this for other Windows APIs:

Using P/Invoke to Call Unmanaged APIs from Your Managed Classes

Calling Win32 DLLs in C# with P/Invoke

PInvoke.net

The attached script files implement two commands.  Set-TimeZone is for setting the current time zone.  Get-TimeZone to get the current time zone information and to list the information for all time zones defined in the Registry.  All five files in the attached Zip need to be in the same folder.  Run Set-TimeZone and Get-TimeZone with the –help switch for usage.

If you want to create similar scripts here are a few tips from what I learn doing this.  First, PowerShell v1 does not like it when you reference the C# classes, structures, etc. in the same script that compiles the code.  I originally had a single library script that contained the here-string with the C# code, the step to compile it and the functions that used it.  This worked fine on v2 but v1 gave me errors that it could not find the C# classes, structures, etc referenced in the functions.  So to get this to work on v1 I had to put the here-string in a separate script (TimeZoneCSharp.ps1) from the functions that use it (TimeZoneLib.ps1).  Then in Get-TimeZone and Set-TimeZone I dot sourced TimeZoneCSharp.ps1 and compiled the C# first, then dot sourced TimeZoneLib.ps1.

Second, if you use the Compile-Csharp function found here you need to comment out the $cpar.OutputAssembly = "custom" line.  This line is not needed since we only want to compile the code in memory.  Also, this line causes the compiler to try to write out an assembly in the Windows\System32 folder.  This makes the script fail when run as as standard user.

Note that Windows 7 now includes a command line utility to set the time zone and get time zone information – tzutil.exe.

Disclaimer: The information on this site is provided "AS IS" with no warranties, confers no rights, and is not supported by the authors or Microsoft Corporation. Use of included script samples are subject to the terms specified in the Terms of Use.

This post was contributed by Michael Murgolo, a Senior Consultant with Microsoft Services - U.S. East Region.

Posted by DeploymentGuys | 1 Comments

Attachment(s): PSTimeZoneScripts.zip

Mark Russinovich - Virtual Round Table on WIndows 7Application Compatibility

While this is not 100% MDT/Deployment focused I thought it of enough relevance to post here. I have attended the Virtual Round Tables that Mark has run in the past. I can say that, without exception, I have found them to be of high value and well worth the time taken out to attend. If you feel this does not appeal to you but would help someone else in your organisation that you know then please pass the information on.

Don't forget that if you have any Application Compatibility Questions you can submit them ahead of time for Mark and the panel to consider.

Springboard Series Virtual Roundtable

Windows 7 Application Compatibility: Your Questions Answered (Part 1)

 

Date:  Thursday, June 18

Time:  11:00am Pacific Time

 

https://ms.istreamplanet.com/springboard

 

Windows 7, is approaching fast and from the application standpoint is very similar to Windows Vista. We’re going to examine Windows 7 application compatibility not only from the perspective of moving from Windows Vista, but also for those coming from Windows XP. Join us to discuss the most common challenges around application compatibility when coming from a legacy operating system, why changes were made along the way, compatibility technologies inside the OS and methods for getting incompatible applications to run on Windows 7. Along the way we share tips and tricks, demonstrate free tools to analyze and fix applications and answer your specific questions about application compatibility live.

 

In Part 2 of this Virtual Round Table discussion (planned for later this Summer/Fall), we’ll discuss the options and approaches for using virtualization tools In depth to address application incompatibilities – including presentation virtualization, desktop virtualization and application virtualization. We’ll be sending out more details and posting information to www.microsoft.com/springboard for part 2 as the dates are finalized.

 

As part of the “virtual” experience, you may submit your questions about Windows 7 Application Compatibility to the panel live during the event—or submit questions in advance to vrtable@microsoft.com.

This post was contributed by Richard Trusson a senior consultant with Microsoft Services UK.

Excluding USB, FireWire and other drives from USMT Capture

A common requirement during user state migration is to not capture data from certain drives.  The most commonly requested for exclusion are removable drives such as USB and FireWire drives.  There is no command line option to exclude these drives automatically with USMT v3.  I had to turn to scripting to accomplish this.

I created a script, ZTI-ExcludeDrivesXmlGen.wsf (and its function library HelperFunctions.vbs), that will generate a USMT XML rules file to unconditionally exclude USB and FireWire drives (as well as additional specified drives) during the deployment.  The script should be run during the State Capture phase before Scanstate.exe is run.  The resulting XML file should be used on both the Scanstate.exe and Loadstate.exe command lines.  The script is driven by either command line switches or MDT properties:

  • Use the /output switch or the USMTExcludeDrivesOutput property to specify the output XML file.  If not specified, the default of oUtility.LogPath & "\MigExcludeDrives.xml" is used.
  • Use the /usb switch or the property USMTExcludeUsbDrives=True to exclude USB and FireWire drives from the migration.
  • Use the /scriptdrive switch or the property USMTExcludeScriptDrive=True to exclude the drive from which this script is running from the migration.
  • Use the /drives switch or the USMTExcludeDrives property to exclude specific drives from the migration.  The switch should be specified like this example:
        /drives:"D:,E:,F:"
    The property should be specified like this example:
        USMTExcludeDrives=D:,E:,F:
  • Use the /flagfile switch or the USMTExcludeDriveFlagFile property to exclude specific drives from the migration using a flag file.  Using the /flagfile switch without a value or setting USMTExcludeDriveFlagFile=True will cause the script to exclude drives that have the default flag file, NO_USMT_ON_DRIVE.USMT, in the root folder of the drive.  (You SMS experts out there will get the choice of the default flag file name.  J )  Using the switch or property with a file name value will exclude drives that have the specified named flag file in the root folder of the drive.

Remember that the generated XML file must also be used with Loadstate.exe.  Therefore, it must be saved to a location that from which it can be retrieved during the State Restore phase.  I have included a script, ZTI-CopyFilesToStateFolder.wsf, to copy files to a subfolder of the state store location that can be used for this.

Disclaimer: The information on this site is provided "AS IS" with no warranties, confers no rights, and is not supported by the authors or Microsoft Corporation. Use of included script samples are subject to the terms specified in the Terms of Use.

This post was contributed by Michael Murgolo, a Senior Consultant with Microsoft Services - U.S. East Region.

Posted by DeploymentGuys | 0 Comments
Filed under: ,

Attachment(s): USMTExcludeDrives.zip

Pin Items to the Start Menu or Windows 7 Taskbar via Script

Update 28 April 2009 – This post originally had the sample scripts pinning the executable (calc.exe) directly.  A colleague of mine pointed out that it would be better to pin the Start Menu shortcuts for items instead of directly pinning the executable.  This should be done because shortcuts for Windows Installer applications are special.  Launching applications using their Windows Installer shortcuts can, for example, initiate a repair of the application it if is needed.  So I have changed all the samples to point to shortcuts.  I have also rewritten the attached script as an MDT script and add added a function library that allows the CSIDL (constant special item ID list) values for “special” folders to be used a variables in the item path.

--------------------------------------------------------------------------------------

Many customers wish to pre-configure items that are “pinned” to the Start Menu in their Windows images.  Also, since items can now be pinned to the new Taskbar in Windows 7, customers will want to configure “pinned” items there as well.

There is no direct programmatic interface to add pinned items to either the Start Menu or Windows 7 Taskbar.  This was done deliberately to prevent installation programs from spamming these locations with their icons (http://blogs.msdn.com/oldnewthing/archive/2003/09/03/54760.aspx).  This caused many customers to have to take manual steps in the image build process to configure pinned items.  However, there is an indirect way to automate this by using the Shell Objects for Scripting.

When you right click on an object (e.g. file or folder icon) in Explorer, you are presented with a menu of actions like Open, Copy, Create Shortcut.  These actions are called verbs in Shell speak.  The Shell Objects for Scripting allow you to enumerate and execute these verb.  Here is a small snippet of code showing how to enumerate the verbs for Calculator:

Const CSIDL_COMMON_PROGRAMS = &H17
Const CSIDL_PROGRAMS = &H2
Set objShell = CreateObject("Shell.Application")
Set objAllUsersProgramsFolder = objShell.NameSpace(CSIDL_COMMON_PROGRAMS)
strAllUsersProgramsPath = objAllUsersProgramsFolder.Self.Path
Set objFolder = objShell.Namespace(strAllUsersProgramsPath & "\Accessories")
Set objFolderItem = objFolder.ParseName("Calculator.lnk")
Set colVerbs = objFolderItem.Verbs
For Each objVerb in colVerbs
    Wscript.Echo objVerb
Next

Below is the output of a small command line script that I wrote (ListVerbs.vbs, included in the attachment) to list the verbs of an item like Calculator.

Verbs2

As you can see, the verbs Pin to Tas&kbar and Pin to Start Men&u are available as verbs for Calculator on my Windows 7 machine. (The & in the verb precedes the letter that can be used to select that verb from the menu using the keyboard.)  We can therefore use the Shell Objects for Scripting to programmatically execute these verbs.  Below is a snippet of VBScript showing how to pin Calculator to the Start Menu:

Const CSIDL_COMMON_PROGRAMS = &H17
Const CSIDL_PROGRAMS = &H2
Set objShell = CreateObject("Shell.Application")
Set objAllUsersProgramsFolder = objShell.NameSpace(CSIDL_COMMON_PROGRAMS)
strAllUsersProgramsPath = objAllUsersProgramsFolder.Self.Path
Set objFolder = objShell.Namespace(strAllUsersProgramsPath & "\Accessories")
Set objFolderItem = objFolder.ParseName("Calculator.lnk")
Set colVerbs = objFolderItem.Verbs
For Each objVerb in colVerbs
    If Replace(objVerb.name, "&", "") = "Pin to Start Menu" Then objVerb.DoIt
Next

I’ve included in the attachment for this post a switch-driven MDT script, PinItem.wsf, that can be used to pin items to the Start Menu or Windows 7 Taskbar.  This can be used during image builds and these additions do survive the automated profile copy mechanisms in XP and Vista (haven’t tested Windows 7 yet but it should work).  It can also be used in logon scripts, etc.  Please note that this script was written for US English verbs.  The verbs for each action would have to be changed in the script for use with another language.

For automated deployments, some of these items can also be configured through an answer file on Windows Vista and higher.  Windows 7 provides an unattend.xml setting to configure up to three Taskbar pinned items (see TaskbarLinks in Microsoft-Windows-Shell-Setup in the Automated Installation Kit documentation).  And both Windows Vista and Windows 7 provide an unattend.xml setting to configure up to five “recently opened programs” on the Start Menu (StartPanelLinks in Microsoft-Windows-Shell-Setup).  However, neither provide a way in unattend.xml to pin items to the Start Menu.

Disclaimer: The information on this site is provided "AS IS" with no warranties, confers no rights, and is not supported by the authors or Microsoft Corporation. Use of included script samples are subject to the terms specified in the Terms of Use.

This post was contributed by Michael Murgolo, a Senior Consultant with Microsoft Services - U.S. East Region.

Posted by DeploymentGuys | 1 Comments

Attachment(s): PinItem.zip

ACT 5.5 Releases April 3rd

An email managed to squeeze its way into my inbox over night announcing that the Application Compatibility Toolkit version 5.5 would be available for download on April 3rd (Redmond Time). This is the version that fully supports Windows 7 RC and Windows Vista SP2.

Here is a preview of some of the features for this release:

· Support for Windows 7 RC and Windows Vista SP2

· Integration of data from the Windows Compatibility Center

· Improved data review and auditing for the information that is sent to Microsoft

· Updated documentation for the Windows compatibility fixes

· Ability to customize your Quick Reports view

· Ability to "label" your individual data collection packages

· Ability to participate in the Customer Experience Program

It is worth pointing out that the Internet Explorer Compatibility Evaluator (IECE) agent has been removed from ACT 5.5. You can continue to detect compatibility issues with Internet Explorer 7 and Internet Explorer 8 Beta, by using the Internet Explorer Compatibility Test Tool (IECTT), which is installed with the ACT, and can be found in the Developer and Tester Tools folder.

If you want to take part in discussions on ACT there is a great public news group here http://microsoft.public.deployment.app_compatibility

This post was contributed by Richard Trusson a senior consultant with Microsoft Services UK.

MDT 2010 Webcast

Michael Niehaus’ walkthrough/webcast of MDT 2010 Beta 2 is now available online as Michael indicates on his blog here:

http://blogs.technet.com/mniehaus/archive/2009/04/01/mdt-2010-partner-webcast-recording-available.aspx

You have to register to download & they have both Live Meeting & WMV formats available.

Register and download here:

http://msevents.microsoft.com/CUI/InviteOnly.aspx?EventID=3A-78-05-A7-61-B7-4B-2B-08-41-98-B1-8C-3B-92-B4&Culture=en-US

 

This post was contributed by Richard Trusson a senior consultant with Microsoft Services UK.

Deploying Windows 7 VL with MAK (Multiple Access Keys) using MDT 2010

My esteemed colleague - Doug Klokow who is a Senior Consultant in the worldwide deployment practice, working with Windows 7 TAP (Technical Adoption Program) customers in the US has put together a most useful set of instructions regarding Windows 7 deployment using MDT 2010 and MAK keys. This is of benefit when deploying to environments where access to KMS may be tricky during the activation timescales – I recently came across this in a university where professors and research staff go off on research assignments for up to a year at a time…When deploying Windows 7 Enterprise Volume License (VL) edition using MDT 2010, it is possible to include a MAK activation key, however, the standard methods of including the key in the unattend.xml file requires modification. Additionally, it is possible to deploy MAK keys using a custom script as part of a Task Sequence.

Situation

While deploying Windows 7 Enterprise VL with MDT 2010, the typical behaviour would be to include the activation key in the customisation wizard used to create a Task Sequence for the deployment of the Windows 7 operating system. By design, the Task Sequence wizard is designed to support retail activation keys, not volume license keys. The difference is subtle, but important to the context of this scenario.

As you complete the New Task Sequence Wizard, you are prompted the Product key.

clip_image002

When you enter a product key into the field shown above, the MDT 2010 wizard adds the code into two specific locations of the unattend.xml file for this task sequence.

clip_image004clip_image006

The first location for the ProductKey is the WindowsPE phase, specifically, the x86_Microsoft-Windows-Setup_neutral\UserData\ProductKey setting.

The second location is in the Specialize phase, specifically the x86_Microsoft-Windows-Shell-Setup_neutral\ProductKey setting.


Issue

The Unattended Windows Setup reference explains why there are two entries for the ProductKey setting, but if the Product Key for Windows 7 Enterprise is placed in both locations (as is the default) when entering the Product Key using the task sequence creation wizard, you will receive the following error when attempting to build or deploy a client machine with that task sequence.

clip_image009


Resolution

There are a number of options available to address this particular situation. Each provides a resolution, but using different methods.

OPTION 1

Simply delete the ProductKey entry in the WindowsPE phase, specifically, the x86_Microsoft-Windows-Setup_neutral\UserData\ProductKey setting. The unattended install should work as expected deploying your Windows 7 machine using the configurations your define. Once the Windows 7 installation is complete, it will be necessary to either manually kick off the activation process from the Computer Properties screen of the machine, or using the Volume Activation Management Tool (VAMT) to complete the activation remotely.

NOTE: At the time this blog was authored, an updated VAMT tool is not presently available with support for Windows 7.

OPTION 2

Use the slmgr.vbs script to perform the activation as a task in the task sequence in lieu of the ProductKey entries in the unattend.xml file. Check the two locations in the unattend.xml file to validate that both entries for ProductKey are blank.

STEP 1: Add the first entry into the Custom Tasks section of the State Restore phase as shown below:

clip_image011

 

Task Name:

Activate Client using VL MAK

Command Line:

cscript.exe c:\windows\system32\slmgr.vbs /ipk XXXXX-XXXXX-XXXXX-XXXXX-XXXXX

Start in:

c:\windows\system32

NOTE: Replace the X's with your VL MAK key for Windows 7

STEP 2: Add the slmgr.vbs /ato script to automatically activate the client during deployment as shown below:

clip_image013

 

Task Name:

Activate the machine using the VL MAK

Command Line:

cscript.exe c:\windows\system32\slmgr.vbs /ato

Start in:

c:\windows\system32

NOTE: This task will only work if the machine is connected to the internet during the State Restore phase. If this task fails because the network connectivity is not fully initialized, it is possible to manually activate the client through the Computer Properties window.

Now when the client machine is deployed, the task sequence will provide the MAK key during the State Restore phase, and attempt to automatically activate the client machine.

OPTION 3

Use the OverRideProductKey entry in the CustomSettings.ini to specify the MAK key to be injected. This will add the MAK product key only into the x86_Microsoft-Windows-Shell-Setup_neutral\ProductKey location in the Unattend.xml.

From the MDT Toolkit Reference document:

OverrideProductKey

The Multiple Activation Key (MAK) string to be applied after the target operating is deployed to the target computer. The value specified in this property is used by the ZTILicensing.wsf script during the State Restore Phase to apply the MAK to the target operating system. The script also configures the volume licensing image to use MAK activation instead of Key Management Service (KMS). The operating system needs to be activated with Microsoft after the MAK is applied. This is used when the target computer is unable to access a server that is running KMS.

Value

Description

MAK

The MAK string to be provided to the target operating system.

Example

[Settings]

Priority=Default

[Default]

ProductKey=AAAAA-BBBBB-CCCCC-DDDDD-EEEEE-FFFFF

OverrideProductKey=AAAAA-BBBBB-CCCCC-DDDDD-EEEEE-FFFFF

Option 4

During deployment, it is possible to specify the Product Key while running the deployment of the workstation. The Deployment Wizard includes an option to prompt for the Product Key using the "SkipProductKey" entry in the CustomSettings.ini file for the Deployment Point. By specifying an entry of "SkipProductKey=No" the user will be prompted to enter a key while running the deployment of the machine, and if they enter their MAK key there, they deployment will complete successfully.

From the MDT Toolkit Reference document:

SkipProductKey

Indicates whether the Specify the product key needed to install this operating system wizard page is skipped.

For other properties that must be configured when this property is set to YES, see the section “Providing Properties for Skipped Windows Deployment Wizard Pages” later in this reference.

Value

Description

YES

Wizard page is not displayed, and the information on that page is not collected.

NO

Wizard page is displayed, and the information on that page is collected. This is the default value.


Example

[Settings]

Priority=Default

[Default]

SkipWizard=NO

SkipCapture=NO

SkipAdminPassword=YES

SkipApplications=NO

SkipAppsOnUpgrade=NO

SkipComputerBackup=NO

SkipDomainMembership=NO

SkipDeploymentType=NO

SkipUserData=NO

SkipPackageDisplay=NO

SkipLocaleSelection=NO

SkipProductKey=YES

Caution This property value must be specified in upper case so that it can be properly read by the deployment scripts.

UPDATE:

If you are working with MDT 2010 Beta 1 then the issue and resolutions referred to above are valid – however our other most esteemed colleague and MDT creator Michael Niehaus has pointed out that the issue has been fixed for MDT 2010 Beta 2.  Now the screen will have another option to match the options that are available in the client-side Deployment Wizard:
clip_image002[1]

Resources

For more information on the using the SLMGR.VBS script for activation tasks, see the Volume Activation 2.0 Deployment Guide.

For more information on the ProductKey setting, see the Unattended Windows Setup Reference.

This post was contributed by Richard Smith a senior consultant with Microsoft Services UK on behalf of Doug Klokow a senior consultant with Microsoft Services US

Posted by DeploymentGuys | 0 Comments
Filed under: , ,

Sharing some simple HTAs

I was recently asked to share these files with a colleague, so I thought I would also share them with everyone via our blog.  I developed them a while ago for a deployment project and I have since used them a few times more.

Basically, they are 3 very simple HTA (HTML application) files that prompt the user for information in order to configure either a static IP address, change the local administrator password, or add a computer to a domain.  Of course, all of these actions can be accomplished directly via MDT, but I had to create them for a very specific reason where MDT could not be used to for this.  They were developed for a Windows XP deployment, so they have not been tested on Windows Vista but I can’t see why they would not work, as long as you ran them elevated.  You can be launch them directly from the task sequence in MDT by using the following command:

mshta.exe CUSTOM_Config_Network.hta

 

CUSTOM_Config_Network.hta

image

CUSTOM_Config_PWD.hta

image

CUSTOM_Config_Domain.hta

image

I have attached the 3 files to this post in a zip file.  Please bare in mind that they are pretty simple and don’t have the error checking for every possible error that might occur, so use at your own risk!

This post was contributed by Daniel Oxley a consultant with Microsoft Services Spain

Disclaimer: The information on this site is provided "AS IS" with no warranties, confers no rights, and is not supported by the authors or Microsoft Corporation. Use of included script samples are subject to the terms specified in the Terms of Use.

Posted by Daniel Oxley | 1 Comments
Attachment(s): SimpleHTAs.zip
More Posts Next page »
 
Page view tracker