Last week I had to modify a Task Sequence created to deploy an x86 version of Windows 7, adding the option to deploy an x64 version of Windows 7. I started with the creation of a x64 Win7 OS master image using a copy of the task sequence used to create the x86 version. To adapt the x86 Task sequence to create an x64 master image, I made the following changes :
- The boot image used should be an x64 version of WinPE, so I built it using the "Create Boot Image using Microsoft Deployment" option added by MDT 2010 to SCCM.
- I changed the package used by the step “Apply Operating System Image” using a new one containing a x64 Version of Windows 7
- I changed the destination value in the step “Capture Operating System Image” to reflect in the name that this is a x64 OS Master image.
We decided to have only 1 task sequence to deploy both x64 and x86 and to select which to apply in our custom HTA already used to collect other user options. Based on the user selection, our HTA has been modified to set a Task Sequence Variable PRG_PLATFORM used later in the task sequence to identify which master image to deploy. After changing the HTA, I didn’t had to modify all the steps in the task sequence, for example an x64 version of WinPE is in not required to deploy Windows 7 x64, USMT 4.0 already supports both platforms, etc. The following is the list of changes I did :
- Added a condition “Task Sequence Variable PRG_PLATFORM equals to ‘x86’” to the step “Apply Operating System Image”
- Added a step “Apply Operating System Image x64” with a condition “Task Sequence Variable PRG_PLATFORM equals to ‘x64’” and with the x64 master image package, previously created using the x64 master image TS.
- Added the condition “Task Sequence Variable PRG_PLATFORM equals to ‘x86’” to all the steps that install software not compatible with Windows 7 x64
- Added steps to install software only compatible with Windows x64 with the condition “Task Sequence Variable PRG_PLATFORM equals to ‘x64’”
- modified the file Unattend.xml to include sections for both processorArchitecture="x86" and processorArchitecture="amd64"
I tested the new task sequence deploying a x64 version of Windows 7 and all worked as expected except that a few customizations done by custom steps were missing. I started checking the scripts used to apply those customization and immediately realized that the problem was caused by the WoW64 redirection :
The following is a snippet of an article published on TechNet Magazine (http://technet.microsoft.com/en-us/magazine/2006.01.insidemscom.aspx) that explain WoW64 redirection :
Redirection Behaviors and Dependencies
It is important for systems engineers to understand how the WoW64 redirection behavior works. There is file system and registry redirection that’s in place to help 32-bit processes work in the 64-bit environment.
File System Redirection Any time a 32-bit process attempts to access c:\windows\system32 the WoW64 layer redirects it into c:\windows\syswow64 which contains all of the 32-bit Windows binaries. This prevents a 32-bit process from trying to load a 64-bit binary. Any scripts or tools running in a 32-bit process that is referencing this directory will be automatically redirected to the syswow64 directory.
Registry Redirection A similar redirection exists for accessing the registry. Any 32-bit process trying to read or write to HKEY_LOCAL_MACHINE\Software gets redirected to HKEY_LOCAL_MACHINE\Software\Wow6432Node\. This allows separate configurations to be maintained for 32-bit and 64-bit processes. Any custom settings or keys set in this node may need to exist in both keys, as 32-bit processes will be redirected to this new branch.
Script Host Bitness Any scripts with dependencies on x86 COM objects need to be run with the 32-bit cscript or wscript. Specify either the 32-bit or 64-bit version of the script host, depending on scripting needs. Any scripts that access the redirected file system or registry are using the correct bitness script host. If a particular script runs with the 32-bit script host, it may use the WoW64 redirection and not have the expected outcome.
I found that the problem with those custom scripts running on an x64 OS is that they try to write some keys under HKLM\Software and to copy some files under %systemroot%\system32 but they ended writing keys under HKLM\SOFTWARE\Wow6432Node and files under “%systemroot%\SysWOW64”. But why redirection is enabled for those scripts? The root cause of this, is that SCCM agent is a 32 bit service even if running on a x64 OS, and so if it executes a Task sequence step of type “Run Command Line” and the command line is “cscript.exe myscript.vbs”, the 32 bit version of cscript located in %systemroot%\SysWoW64 is executed instead of the 64 bit version located in %SystemRoot%\System32. So, to solve my problem I had 2 choice :
- Force SCCM to execute the 64 bit version of cscript when running on x64 platforms
- Change those script to be aware of redirection and write in the not redirected paths when running on x64 platforms
SCCM has an option to disable Redirection on x64 platforms, so I tried the first choice using this feature :
With this check enabled some of the steps started to complete successfully, but not all them. I started to debug one of the failing script and I found that the script was unable to read the value of a Task Sequence Variable using the functions provided by the Class Environment defined in ZTIUtility.vbs. For reading and writing Task Sequence Variables the Class Environment uses the COM Object Microsoft.SMS.TSEnvironment but I found that if using a 64-bit version of cscript the creation of the COM object fails. The problem is that Microsoft.SMS.TSEnvironment is a 32-bit COM Object and it is not available in a 64-bit environment (Script Host Bitness). With this limitation I decided to abandon the first choice of disabling redirection and I started to change those scripts to be aware of redirection.
To create a script that is redirection aware, the first step is to identify if the Operating System in which the script is running is a 64-bit OS, to do that I used the following Function to check the Processor Architecture :
if lcase(oShell.Environment("SYSTEM")("Processor_Architecture")) = "amd64" Then
PRG_Isx64 = True
PRG_Isx64 = False
To access the x64 System32 folder from a 32-bit application I used the alias sysnative as explained in the following article :
32-bit applications can access the native system directory by substituting %windir%\Sysnative for %windir%\System32. WOW64 recognizes Sysnative as a special alias used to indicate that the file system should not redirect the access. This mechanism is flexible and easy to use, therefore, it is the recommended mechanism to bypass file system redirection. Note that 64-bit applications cannot use the Sysnative alias as it is a virtual directory not a real one.
Windows Server 2003 and Windows XP: The Sysnative alias was added starting with Windows Vista.
The following is an example on how I used the previous function and the alias to have a variable containing the path to the not redirected system32 folder.
If (PRG_Isx64) Then
sSysDir = oEnv("WINDIR") & "\sysNative"
sSysDir = oEnv("WINDIR") & "\SYSTEM32"
Unfortunately I was not able to find an alias to access the 64 bit registry software key under a 32-bit application, so with a suggestion coming from Daniele I used WMI and the __ProviderArchitecture flag. I created a function PRG_RegWrite with the same parameters as the method RegWrite of the Wscript.Shell Object to be able to easily replace it in my scripts :
Const HKEY_CLASSES_ROOT = &H80000000
Const HKEY_CURRENT_USER = &H80000001
const HKEY_LOCAL_MACHINE = &H80000002
const HKEY_USERS = &H80000003
const HKEY_CURRENT_CONFIG = &H80000005
Function PRG_RegWrite(szKey, sValue, sType)
Dim strKeyPath, strValueName, sKey
Dim objCtx, objLocator, objServices, objReg, sDelim
Dim iCount, iMax, lRet, isKey
if (PRG_Isx64) Then
aKeys = Split(trim(szKey),"\")
iCount = 0
sKey = ucase(aKeys(0))
if sKey = "HKLM" or sKey = "HKEY_LOCAL_MACHINE" Then
rKey = HKEY_LOCAL_MACHINE
elseif sKey = "HKCU" or sKey = "HKEY_CURRENT_USER" Then
rKey = HKEY_CURRENT_USER
elseif sKey = "HKCR" or sKey = "HKEY_CLASSES_ROOT" Then
rKey = HKEY_CLASSES_ROOT
elseif sKey = "HKEY_USERS" or sKey = "HKEY_USERS" Then
rKey = HKEY_USERS
elseif sKey = "HKEY_CURRENT_CONFIG" or sKey = "HKEY_CURRENT_CONFIG" Then
rKey = HKEY_CURRENT_CONFIG
Err.Raise 87,"PRG_RegWrite","Invalid HKEY Specified"
Set objCtx = CreateObject("WbemScripting.SWbemNamedValueSet")
objCtx.Add "__ProviderArchitecture", 64
Set objLocator = CreateObject("Wbemscripting.SWbemLocator")
Set objServices = objLocator.ConnectServer("","root\default","","",,,,objCtx)
Set objReg = objServices.Get("StdRegProv")
iMax = ubound(aKeys)
if aKeys(iMax) = "" then
isKey = true
strValueName = aKeys(iMax)
isKey = false
sDelim = ""
for iCount = 1 to iMax – 1
strKeyPath = strKeyPath & sDelim & aKeys(iCount)
lRet = objReg.CreateKey(rKey, strKeyPath)
sDelim = "\"
if lRet <> 0 then
if isKey = false and lRet = 0 Then
sType = UCASE(sType)
if sType = "REG_SZ" then
lRet = objReg.SetStringValue(rKey,strKeyPath,strValueName,sValue)
elseif sType = "REG_DWORD" then
lRet = objReg.SetDWORDValue(rKey,strKeyPath,strValueName,sValue)
elseif sType = "REG_BINARY" then
lRet = objReg.SetBinaryValue(rKey,strKeyPath,strValueName,sValue)
elseif sType = "REG_EXPAND_SZ" then
lRet = objReg.SetExpandedStringValue(rKey,strKeyPath,strValueName,sValue)
lRet = objReg.SetStringValue(rKey,strKeyPath,strValueName,sValue)
Set objCtx = Nothing
Set objLocator = Nothing
Set objServices = Nothing
Set objReg = Nothing
if lRet <> 0 Then
Err.Raise 87,"PRG_RegWrite","Error during Write Operation : (" & lRet & ")"
oShell.RegWrite szKey, sValue, sType
After those customizations I was able to have a single task sequence to deploy both platforms, I hope this help if someone else need to achieve the same result.
This posting is provided “AS IS” with no warranties, and confers no rights.