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 :
Function PRG_Isx64
if lcase(oShell.Environment("SYSTEM")("Processor_Architecture")) = "amd64" Then
PRG_Isx64 = True
else
PRG_Isx64 = False
End if
End Function
To access the x64 System32 folder from a 32-bit application I used the alias sysnative as explained in the following article :
http://msdn.microsoft.com/en-us/library/aa384187(v=VS.85).aspx
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"
Else
sSysDir = oEnv("WINDIR") & "\SYSTEM32"
End if
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 aKeys
Dim rKey
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
else
Err.Raise 87,"PRG_RegWrite","Invalid HKEY Specified"
Exit function
End if
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
else
strValueName = aKeys(iMax)
isKey = false
End if
sDelim = ""
for iCount = 1 to iMax – 1
strKeyPath = strKeyPath & sDelim & aKeys(iCount)
lRet = objReg.CreateKey(rKey, strKeyPath)
sDelim = "\"
if lRet <> 0 then
exit for
end if
next
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)
else
lRet = objReg.SetStringValue(rKey,strKeyPath,strValueName,sValue)
end if
End if
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 & ")"
end if
else
oShell.RegWrite szKey, sValue, sType
End if
End Function
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.
– Fabrizio
This posting is provided “AS IS” with no warranties, and confers no rights.
#1 by Amron on September 30, 2013 - 6:15 pm
I’m using VBS scripts to move the machine object in AD to the correct OU. Works great with XP but not with Win7 x64. So I understand that it has to do with the inability to access the COM Object. So what do I need to do in order to get these VBS scripts to work? Do I just go ahead and modify the ZTIUtility.vbs with the “Function PRG_Isx64”? If so, then how will ZTIConfigure.wsf work? Any advice would be great.
#2 by Keira on June 7, 2013 - 11:45 am
Hey very nice website!! Guy .. Excellent .. Wonderful .. I’ll bookmark your site and take the feeds also? I’m happy to find a lot of useful info here
in the put up, we want develop extra strategies on this regard, thanks
for sharing. . . . . .
#3 by Virimai Mare on July 23, 2012 - 3:09 pm
Hi, Please help.
How did you manage to set-up your Task Sequence will the information. Can you please send me the task sequence
#4 by Daniele Grandini on July 26, 2012 - 3:52 pm
sorry but I cannot share the task sequence
#5 by berry on April 29, 2010 - 5:42 pm
i think i really like your blog. keep posting good articel dude..!