Using PowerShell to make changes in Offline Registry

Here is a quick example for using PowerShell to make changes in offline registry in a ConfigMgr task sequence. If using a different deployment solution simply replace the logic to locate the offline image.

# Figure out if we can use the task sequence object
try {
		$TSEnv = New-Object -ComObject Microsoft.SMS.TSEnvironment -ErrorAction Stop
}
catch [System.Exception] {
	Write-Warning -Message "Unable to create Microsoft.SMS.TSEnvironment object, aborting..."
    Break
}

$LogPath = $TSEnv.Value("_SMSTSLogPath") 
$Logfile = "$LogPath\DisableWindowsUpdates.log"

# Delete any existing logfile if it exists
If (Test-Path $Logfile){Remove-Item $Logfile -Force -ErrorAction SilentlyContinue -Confirm:$false}

Function Write-Log{
	param (
    [Parameter(Mandatory = $true)]
    [string]$Message
   )

   $TimeGenerated = $(Get-Date -UFormat "%D %T")
   $Line = "$TimeGenerated : $Message"
   Add-Content -Value $Line -Path $LogFile -Encoding Ascii

}

# Load the offline registry hive from the OS volume
$OSDTargetSystemDrive = $TSEnv.Value("OSDTargetSystemDrive")
$HivePath = "$OSDTargetSystemDrive\Windows\System32\config\SOFTWARE"
Write-Log -Message "About to load registry hive: $HivePath "
reg load "HKLM\NewOS" $HivePath 
Start-Sleep -Seconds 5

# Updating offline registry to disable Windows updates
Write-Log -Message "Updating registry to disable Windows updates"
$RegistryKey = "HKLM:\NewOS\Policies\Microsoft\Windows\WindowsUpdate\AU" 
Write-Log -Message "Creating registry key: $RegistryKey"
$Result = New-Item -Path $RegistryKey -ItemType Directory -Force
$Result.Handle.Close()

$RegistryValue = "NoAutoUpdate"
$RegistryValueType = "DWord"
$RegistryValueData = 1
    # 0 = Updates Enabled
    # 1 = Updates Disabled
Write-Log -Message "Creating registry value: $RegistryValue, value type: $RegistryValueType, value data: $RegistryValueData"
$Result = New-ItemProperty -Path $RegistryKey -Name $RegistryValue -PropertyType $RegistryValueType -Value $RegistryValueData -Force


# Cleanup (to prevent access denied issue unloading the registry hive)
Remove-Variable Result
Get-Variable Registry* | Remove-Variable
[gc]::collect()
Start-Sleep -Seconds 5

# Unload the registry hive
Write-Log -Message "Unloading the registry hive"
Set-Location X:\
reg unload "HKLM\NewOS"  
Running the script in a Task Sequence
About the author

Johan Arwidmark

5 3 votes
Article Rating
Subscribe
Notify of
guest
6 Comments
Newest
Oldest Most Voted
Inline Feedbacks
View all comments
dsraa
dsraa
6 months ago

Hi Johan, I like this approach and may begin using it as opposed to individual registry change steps, but why not use a function so you can use it for multiple registry changes and you wouldn't have to redefine the variables each time? Would this be possible?

George Simos
7 months ago

Great article Johan, I have done something similar in September to accommodate a regsitry addition in the user's RunOnce section. It was tricky but our solutions are close 🙂
I can share the code if you want.

Last edited 7 months ago by George Simos
George Simos
3 months ago
Reply to  George Simos

I did shared 🙂 Any comments welcome!

Chris
7 months ago

I really appreciate the expertise that this simple post provided… I have been trying unsuccessfully for about a week to figure out why PowerShell did not seem to be able to unload the hive (I could spot exactly what the problem was but couldn't identify why the process was still being held hostage)… Thank you, Johan! As usual, your experience in these matters is PRICELESS!


>