PowerShell registry hive unload error

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”

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.

It seems the hive is successfully unloaded when the PSSesion is removed (Remove-PSSession -Id $PSS.Id ) - not sure if it really is though and I would expect the correct method is the one I am attempting - reg unload “HKU$($args[0])”

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

You may try to set “Remove-PSDrive” before “reg unload” and “[gc]::collect()”, but you task is simple, so you can use “reg delete” instead of “Clear-ItemProperty”, so powershell not involved in registry tasks and can’t block unloading

Hi Max, thank you for your reply. I have tried every variation of “Remove-PSDrive” before “reg unload” and “[gc]::collect()” In any order it still fails to unload the hive until “Remove-PSSession -Id $PSS.Id” occurs.

As far as the tasks are concerned - In this example I just used one, the actual script performs a very large number of changes using different procedures on HKU. Loading the hive is unavoidable.

Here’s another clue - If I RDP onto the target machine, I see the hive load as the script tells it to, but if I pause the script there I cannot manually unload the hive, it says access is denied, so PowerShell is definitely holding it open.

Any further advice would be greatly appreciated.

so, you can run subprocess inside your session

{
  reg load
    powershell.exe yourscripthere...
  reg unload
}

this way other powershell lock your registry, but it closes before ‘reg unload’

but I prefer using remote registry .net methods:

remotely: {
  reg load ...
}
locally:
{
  $reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('Users', $ComputerName)
  try {
    ...
  }
  finally {
    $reg.Close()
  }
}
remotely:
{
  reg unload ...
}

Thanks Max, I will research what “subprocess inside your session” means because I am not sure, even with your example. I dont want to waste you’re time but if you can - please expand my example script to describe what you mean.

Thanks a lot,
Ian

something like this…

$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 {

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

powershell -command @'
New-PSDrive -PSProvider Registry -Name HKU -Root HKEY_USERS
Clear-ItemProperty -Path
 "HKU:\$($args[0])\SOFTWARE\Microsoft\Office\Common\UserInfo" -Name
 "UserInitials" 
Remove-PSDrive -Name HKU
@' -argumentlist $args[0]

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

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

}

Remove-PSSession -Id $PSS.Id 

Thanks Max - I will try this out and let you know.
:slight_smile:

Good Day Everyone,

Two questions about the above. First is there a way to mount and unmount DAT files without using reg.exe?
Second I am trying to capture the results and running into issues. Is this a case of reg.exe was written the way it is and you only get the output string? I have tried:

$RegUnLoad = & REG UNLOAD HKLM\DEFAULT

This captures the output to a string, but I was hoping for an error code ($LastExitCode) on messages like access denied. I am following the robocopy example at An Introduction to Error Handling in PowerShell | Microsoft Docs