PowerShell registry hive unload error

Viewed 1257

I have hit a problem I haven’t been able to solve despite trying quite hard.

Basically I have created a PowerShell script to alter\change values in the HKU hive for a specific user on a remote Windows 10 Amazon WorkSpace. The script loads the hive and makes the changes perfectly but I am getting an error when trying to unload the hive. I have tried various methods as suggested on different forums but to no avail. Here is the part of the script I’m having trouble with:

$WorkSpace = "blahComputerName"
$PSS = New-PSSession -ComputerName $WorkSpace
$UserAcc = "XXXXX"
$SID = (Get-ADUser -server MyDomain.com -Identity $UserAcc).SID.Value

    Invoke-Command -Session $PSS -ArgumentList $SID, $UserAcc -ScriptBlock {


New-PSDrive -PSProvider Registry -Name HKU -Root HKEY_USERS

reg load "HKU\$($args[0])" "D:\Users\$($args[1])\NTUser.Dat" 

Clear-ItemProperty -Path 
"HKU:\$($args[0])\SOFTWARE\Microsoft\Office\Common\UserInfo" -Name 
"UserInitials" 

[gc]::collect()
Start-Sleep -Seconds 5

reg unload "HKU\$($args[0])"  


Remove-PSDrive -Name HKU

}

Remove-PSSession -Id $PSS.Id  

I have also read that using $SomeThing.Handle.Close() will close any open handles PowerShell might still have with the provider which might be causing the error but I can’t see how to use it in this context.

Here is the exact error:

ERROR: Access is denied. + CategoryInfo : NotSpecified: (ERROR: Access is denied.:String) [], RemoteException + FullyQualifiedErrorId : NativeCommandError + PSComputerName : blahComputerName

I have manually observed the remote registry hive being loaded and then apparently unloaded but this error worries me and would like to solve it. I have proved that its reg unload "HKU\$($args[0])" that is causing the error but cant find the correct solution.

The script runs with the required elevated privileges, so it’s not that. The remote WorkSpace is in a logged off state.

Any advice would be greatly appreciated. Thank You

2 Answers

Though Garbage collection is nice, the problem stems from how this command is handled;

Clear-ItemProperty -Path 
"HKU:\$($args[0])\SOFTWARE\Microsoft\Office\Common\UserInfo" -Name 
"UserInitials" 

I would recommend capturing it in a variable, like so;

$n = Clear-ItemProperty -Path "HKU:\$($args[0])\SOFTWARE\Microsoft\Office\Common\UserInfo" -Name "UserInitials" 

Which should allow you to properly clean it up, like so;

$n.dispose()
$n.close()

Note the above is likely redundant (Dispose should close, and close should call dispose).

With the help of other examples I figured it out. Here's what needs to be done:

$tempHive = 'HKLM\TEMP_hive'
$ntUserFile = 'C:\Users\SOME_USER\NTUSER.DAT'

# Load hive
$startParams = @{
    FilePath     = 'reg.exe'
    ArgumentList = "load `"$tempHive`" `"$ntUserFile`"" 
    WindowStyle  = 'Hidden'
    Wait         = $true
    PassThru     = $true
}
$process = Start-Process @startParams
if ($process.ExitCode) {
   throw "Failed to load the temp hive '$tempHive' for '$ntUserFile': exit code $($process.ExitCode)"
}

# make registry hive drive mapping if needed
# New-Psdrive -name <blah> -PSProvider Registry -root <blih>

# close open handles for 'New-Item'
$result = New-Item -Path "HKLM:\TEMP_hive\newkey"
$result.Handle.Close()

# no need to close open handles from 'New-ItemProperty'
# $null = New-ItemProperty @newParams

# wait for garbage clean up
[gc]::Collect()
[gc]::WaitForPendingFinalizers()

# if you did drive mapping with the mapped registry hive remove it before unload
# Remove-PSDrive <blah>

# unload the hive
$startParams = @{
    FilePath     = 'reg.exe'
    ArgumentList = "unload `"$tempHive`""
    WindowStyle  = 'Hidden'
    Wait         = $true
    PassThru     = $true
}
$process = Start-Process @startParams
if ($process.ExitCode) {
   throw "Failed to unload the temp hive '$tempHive' for '$ntUserFile': exit code $($process.ExitCode)"
}
Related