none
How to run a task sequence step in Windows PE? RRS feed

  • Question

  • Hi,

    I am using MDT 2013, and have a situation where I would like to modify the registry from Windows PE after having installed a number of applications - before capturing the image.

    This must be something that is possible, and I see all sorts of promising hints in the TS.XML referring to rebooting with target:winpe, and so on, but I cannot get it to happen, and I don't seem to be able to find any documentation about how it should work, or anyone else that mentions it!

    Can someone point me in the right direction?

    Thanks

    Wednesday, July 9, 2014 12:07 PM

Answers

  • I've got something similar formatted as a .wsf, I'm running it in the PostInstall phase at deploy time. This example removes the Lync run key from the registry, but you could modify it to do whatever you want.

    ' //----------------------------------------------------------------------------
    ' //
    ' // File: ZTI_OfflineRegedit
    ' //
    ' // Purpose: Runs in WinPE, during POSTINSTALL phase
    ' // 	imports registry hive and edits
    ' //
    ' // Author: Joe Sestrich
    ' //
    ' // Usage: cscript ZTI_OfflineRegedit [/debug:true]
    ' //
    ' //----------------------------------------------------------------------------
    
    '//----------------------------------------------------------------------------
    '//
    '// Global constant and variable declarations
    '//
    '//----------------------------------------------------------------------------
    
    Option Explicit
    
    Dim iRetVal
    Dim regVal, Return
    
    Dim strOSDisk, strHiveLocation, strImportKey, strRootKey, strImportHive
    Dim strRegData, strRegCmd, strRegPath, strRegValue
    Dim VALUE, VALUE2
    
    Dim ArgObj
    Set ArgObj = WScript.Arguments  ' These Arguements read from the command line each segmented input to create a variable
    
    '//----------------------------------------------------------------------------
    '// End declarations
    '//----------------------------------------------------------------------------
    
    '//----------------------------------------------------------------------------
    '// Main routine
    '//----------------------------------------------------------------------------
    
    On Error Resume Next
    iRetVal = ZTIProcess
    ProcessResults iRetVal
    On Error Goto 0
    
    '//---------------------------------------------------------------------------
    '// Function: ZTIProcess()
    '//---------------------------------------------------------------------------
    
    Function ZTIProcess()
    
    'Import HKLM\Software To WinPE for editing
    strOSDisk = oEnvironment.Item("SMSTSLocalDataDrive")
    oLogging.CreateEntry "OSDisk detected as: " & strOSDisk, LogTypeInfo
    strHiveLocation = strOSDisk & "\Windows\System32\config"
    oLogging.CreateEntry "Loading hive from: " & strHiveLocation, LogTypeInfo
    strRootKey = "HKLM"
    strImportHive = "SOFTWARE"
    strImportKey = "TEMP_SFW"
    
    
    ' strRootKey = ArgObj(0)
    ' strImportHive = ArgObj(1)
    ' strRegPath = ArgObj(2)
    
    If UCase(oEnvironment.Item("Architecture")) = "X64" Then
     	strRegPath = "Wow6432Node\Microsoft\Windows\CurrentVersion\Run\Communicator"
    Else
    	strRegPath = "Microsoft\Windows\CurrentVersion\Run\Communicator"
    End If
    
    strRegValue = strRootKey & "\" & strImportKey & "\" & strRegPath
    
    oLogging.CreateEntry "Importing registry hive from location: " & strHiveLocation & "\" & strImportHive, LogTypeInfo
    
    If oFSO.FileExists(strHiveLocation & "\" & strImportHive) Then
    	strRegCmd = "reg.exe" & " " & "load " & strRootKey & "\" & strImportKey & " " & Chr(34) & strHiveLocation & "\" & strImportHive & Chr(34)
    	oLogging.CreateEntry "Running command: " & strRegCmd, LogTypeInfo
    	oShell.Run strRegCmd, 1, True
    
    Else
    	oLogging.CreateEntry "Running command: " &  "Can't find hive " & strHiveLocation & "\" & strImportHive & ". Exiting", LogTypeError
    	WScript.Quit
    
    End If
    
    'Call to Sub
      DeleteValue(strRegValue)
    
    oLogging.CreateEntry "reg.exe"  & " " & "unload " & strRootKey & "\" & strImportKey, LogTypeInfo
    oShell.Run  "reg.exe" & " " & "unload " & strRootKey & "\" & strImportKey, 1, True
    
    oLogging.CreateEntry "Finished ZTI_OfflineRegedit", LogTypeInfo   
    
    If (iRetVal = 0) or (iRetVal = 3010) Then
        ZTIProcess = Success
    Else
        ZTIProcess = Failure
    End If
    End Function
    
    
    Sub DeleteValue(VALUE)
    oLogging.CreateEntry "Reading value at " & strRegValue, LogTypeInfo
    
    If RegistryValueExists(VALUE) Then
     	oLogging.CreateEntry "Reg value " & VALUE & " exists, deleting it", LogTypeInfo
    	strRegData = oShell.RegDelete(VALUE) 
    Else
     	oLogging.CreateEntry "Reg Value does not exist, no change required", LogTypeWarning
    End If
     
     End Sub
     
    '*****************************************************
    '* RegistryValueExists Function Returns (true / false)
    '*****************************************************
    
    Function RegistryValueExists(VALUE2)
      'Ensure the last character is NOT a backslash (\) - if it is, we aren't looking for a value
      If (Right(VALUE2, 1) = "\") Then
        'It's not a registry value we are looking for
        RegistryValueExists = false
      Else
        'If there isnt the value when we read it, it will return an error, so we need to resume
        On Error Resume Next
    
        'Try reading the value
        oShell.RegRead VALUE2
    
        'Catch the error
        Select Case Err
          Case 0:
            'Error Code 0 = 'success'
            RegistryValueExists = true
          Case Else
            'Any other error code is a failure code
            RegistryValueExists = false
        End Select
    
        'Turn error reporting back on
        On Error Goto 0
      End If
    End Function

    Thursday, July 10, 2014 3:50 PM

All replies

  • What are you attempting to accomplish with this? Couldn't you simply make your registry change in Windows before you capture the image, since MDT does not install applications in Windows PE? Why do you need to make the change in Windows PE?

    -Nick O.

    Wednesday, July 9, 2014 3:28 PM
  • Hi Nick,

    Thanks for the response.

    Strange that I seem to be the only person that has a problem deploying an image with a Host Intrusion Prevention Software package pre-installed! This particular package won't let the services be disabled under Windows (kind of logical), so PE is the place to do it. That takes care of 2 of your questions.

    In the meantime I did figure out how to do it, and although it is not exactly elegant, it does work. And my solution is directly related to your second question. I simply duplicated the whole apply pe section from the image capture group and it works fine.

    I did this before I read your answer, but now I am asking myself whether or not I can just put my script in before the image capture - I will have to check what the security software does in the short time between installation and image capture...

    Either way, I have a solution, even if I was hoping for a rather more "elegant" one!

    Thursday, July 10, 2014 7:46 AM
  • If you cannot do the registry changes before installing IPS. The do this in WinPE by mounting the registry. Do the change and then unmount the registry.

    I've two functions I use in a UserExit.vbs script. I think you can adapt them for what you need.

    Private Function MountOfflineRegistry()
    	oLogging.CreateEntry "Entered MountOfflineRegistry", LogTypeInfo
    	Dim iRet, drv, sOldSystem
    	sOldSystem = ""
    	For Each drv In Array("C", "D", "E", "F")
    		oLogging.CreateEntry "Checking drive " & drv & " for registry", LogTypeInfo
    		If ofso.FileExists(drv & ":\windows\system32\config\system") Then
    			sOldSystem = drv & ":\windows\system32\config\system"
    			Exit For
    		End If
    	Next
    	
    	If sOldSystem <> "" Then
    		oLogging.CreateEntry "Found offline registry at " & sOldSystem, LogTypeInfo
    
    	Else
    		oLogging.CreateEntry "Could not find old system registry.", LogTypeInfo
    		MountOfflineRegistry = False
    		Exit Function
    	End If
    	
    	oLogging.CreateEntry "Mounting Offline registry " & sOldSystem, LogTypeInfo
    	On Error Resume Next
    	iret = oShell.Run ("reg load HKLM\z " & sOldSystem, 0, True)
    	On Error Goto 0
    	If iRet <> 0 Then
    		oLogging.CreateEntry "Could not mount offline registry. Code returned " & iRet, LogTypeInfo
    		MountOfflineRegistry = False
    		Exit Function
    	Else
    		oLogging.CreateEntry "Offline registry now mounted at HKLM\z", LogTypeInfo 
    		MountOfflineRegistry = True
    		Exit Function
    	End if
    End Function
    
    Private Function UnMountOfflineRegistry()
    	Dim iRet
    	oLogging.CreateEntry "Entered UnMountOfflineRegistry", LogTypeInfo
    	oLogging.CreateEntry "About to unmount offline registry", LogtypeInfo
    	On Error Resume Next
    	iRet = oShell.Run("REG UNLOAD HKLM\Z", 0, True)
    	On Error Goto 0
    	If iRet <> 0 Then
    		oLogging.CreateEntry "Could not unmount offline registry. Code returned " & iRet, LogTypeInfo
    		UnMountOfflineRegistry = False
    	Else
    		oLogging.CreateEntry "Offline registry now unmounted", LogTypeInfo
    		UnMountOfflineRegistry = True
    	End If
    End Function
    

    Thursday, July 10, 2014 3:08 PM
  • I've got something similar formatted as a .wsf, I'm running it in the PostInstall phase at deploy time. This example removes the Lync run key from the registry, but you could modify it to do whatever you want.

    ' //----------------------------------------------------------------------------
    ' //
    ' // File: ZTI_OfflineRegedit
    ' //
    ' // Purpose: Runs in WinPE, during POSTINSTALL phase
    ' // 	imports registry hive and edits
    ' //
    ' // Author: Joe Sestrich
    ' //
    ' // Usage: cscript ZTI_OfflineRegedit [/debug:true]
    ' //
    ' //----------------------------------------------------------------------------
    
    '//----------------------------------------------------------------------------
    '//
    '// Global constant and variable declarations
    '//
    '//----------------------------------------------------------------------------
    
    Option Explicit
    
    Dim iRetVal
    Dim regVal, Return
    
    Dim strOSDisk, strHiveLocation, strImportKey, strRootKey, strImportHive
    Dim strRegData, strRegCmd, strRegPath, strRegValue
    Dim VALUE, VALUE2
    
    Dim ArgObj
    Set ArgObj = WScript.Arguments  ' These Arguements read from the command line each segmented input to create a variable
    
    '//----------------------------------------------------------------------------
    '// End declarations
    '//----------------------------------------------------------------------------
    
    '//----------------------------------------------------------------------------
    '// Main routine
    '//----------------------------------------------------------------------------
    
    On Error Resume Next
    iRetVal = ZTIProcess
    ProcessResults iRetVal
    On Error Goto 0
    
    '//---------------------------------------------------------------------------
    '// Function: ZTIProcess()
    '//---------------------------------------------------------------------------
    
    Function ZTIProcess()
    
    'Import HKLM\Software To WinPE for editing
    strOSDisk = oEnvironment.Item("SMSTSLocalDataDrive")
    oLogging.CreateEntry "OSDisk detected as: " & strOSDisk, LogTypeInfo
    strHiveLocation = strOSDisk & "\Windows\System32\config"
    oLogging.CreateEntry "Loading hive from: " & strHiveLocation, LogTypeInfo
    strRootKey = "HKLM"
    strImportHive = "SOFTWARE"
    strImportKey = "TEMP_SFW"
    
    
    ' strRootKey = ArgObj(0)
    ' strImportHive = ArgObj(1)
    ' strRegPath = ArgObj(2)
    
    If UCase(oEnvironment.Item("Architecture")) = "X64" Then
     	strRegPath = "Wow6432Node\Microsoft\Windows\CurrentVersion\Run\Communicator"
    Else
    	strRegPath = "Microsoft\Windows\CurrentVersion\Run\Communicator"
    End If
    
    strRegValue = strRootKey & "\" & strImportKey & "\" & strRegPath
    
    oLogging.CreateEntry "Importing registry hive from location: " & strHiveLocation & "\" & strImportHive, LogTypeInfo
    
    If oFSO.FileExists(strHiveLocation & "\" & strImportHive) Then
    	strRegCmd = "reg.exe" & " " & "load " & strRootKey & "\" & strImportKey & " " & Chr(34) & strHiveLocation & "\" & strImportHive & Chr(34)
    	oLogging.CreateEntry "Running command: " & strRegCmd, LogTypeInfo
    	oShell.Run strRegCmd, 1, True
    
    Else
    	oLogging.CreateEntry "Running command: " &  "Can't find hive " & strHiveLocation & "\" & strImportHive & ". Exiting", LogTypeError
    	WScript.Quit
    
    End If
    
    'Call to Sub
      DeleteValue(strRegValue)
    
    oLogging.CreateEntry "reg.exe"  & " " & "unload " & strRootKey & "\" & strImportKey, LogTypeInfo
    oShell.Run  "reg.exe" & " " & "unload " & strRootKey & "\" & strImportKey, 1, True
    
    oLogging.CreateEntry "Finished ZTI_OfflineRegedit", LogTypeInfo   
    
    If (iRetVal = 0) or (iRetVal = 3010) Then
        ZTIProcess = Success
    Else
        ZTIProcess = Failure
    End If
    End Function
    
    
    Sub DeleteValue(VALUE)
    oLogging.CreateEntry "Reading value at " & strRegValue, LogTypeInfo
    
    If RegistryValueExists(VALUE) Then
     	oLogging.CreateEntry "Reg value " & VALUE & " exists, deleting it", LogTypeInfo
    	strRegData = oShell.RegDelete(VALUE) 
    Else
     	oLogging.CreateEntry "Reg Value does not exist, no change required", LogTypeWarning
    End If
     
     End Sub
     
    '*****************************************************
    '* RegistryValueExists Function Returns (true / false)
    '*****************************************************
    
    Function RegistryValueExists(VALUE2)
      'Ensure the last character is NOT a backslash (\) - if it is, we aren't looking for a value
      If (Right(VALUE2, 1) = "\") Then
        'It's not a registry value we are looking for
        RegistryValueExists = false
      Else
        'If there isnt the value when we read it, it will return an error, so we need to resume
        On Error Resume Next
    
        'Try reading the value
        oShell.RegRead VALUE2
    
        'Catch the error
        Select Case Err
          Case 0:
            'Error Code 0 = 'success'
            RegistryValueExists = true
          Case Else
            'Any other error code is a failure code
            RegistryValueExists = false
        End Select
    
        'Turn error reporting back on
        On Error Goto 0
      End If
    End Function

    Thursday, July 10, 2014 3:50 PM
  • JoeZeppy; Nice wsf script.

    SkippyNeedsaBeer; Another thing I thougt about yesterday. Will sysprep work with Host Intrution Prevention Software? At my work McAfee HIPS will not allow of our logon vbs script.
    
    
    Friday, July 11, 2014 7:49 AM
  • Thanks everyone for the examples - to be honest I already have everything I need  to modify the registry, but it is always nice to see how others solve the same challenge! It was just actually getting the task sequence into PE that was causing me a headache.

    I have since decided to put my task right before the image capture, and disable the services there. Sysprep was able to run with the HIPS configuration here, and after the reboot, setup is also fine.

    My attempt to duplicate the reboot into PE and then back into Windows somehow failed - after resetting the BCD to boot windows, and restarting, it did indeed boot into windows, but the TS never resumed.

    The sequence I tried was:

    - Apply Windows PE
    - Apply Windows PE (BCD)
    - Restart Computer
    - Run WinPE Commands (my script)
    - Remove MDT BCD (does a bcdedit /delete {current}
    - Restart Computer

    At this point I would expect the TS to continue but that is the last I see!

    Friday, July 11, 2014 11:37 AM