Here are some tips and trick on how to work on the Windows Registry with Powershell.
Basics
While the terminology of the Windows Registry is somewhat confusing, that’s what we just have to deal with…
$RootKey = "HKLM:\" # = HKEY_LOCAL_MACHINE
$Key = $RootKey + "SYSTEM\CurrentControlSet\Control\FileSystem\"
$Value = "LongPathsEnabled"
A value can store data as payload in different types, for example a string (REG_SZ
: “Hello, world!”), or a 32-bit unsigned integer (REG_DWORD
: 123), or some other format.
To get the item itself, use this:
Get-Item HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem\LongPathsEnabled
Get-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem\ -Name LongPathsEnabled
Or, to get just the actual data (payload) of a specific value, use this:
(Get-ItemProperty -Path $Key -Name $Value).Value # Powershell < Version 5.
Get-ItemPropertyValue -Path $Key -Name $Value # Powershell >= Version 5.
Gotcha: RegEdit vs. Powershell
While trying to automate a few work steps that I did before by hand for a remote computer, I stumbled upon an interesting difference between handling the Registry via the RegEdit program and a Powershell script:
When you run regedit.exe, you will see a User Account Control prompt asking for the administrator credentials (“Do you want to allow this app to make changes to your device?”). If you do not provide a password and do not confirm elevation, the app won’t start.
However, regedit should run as administrator by default when you open Registry Editor while signed in to an administrator account.
— https://www.reddit.com/r/PowerShell/comments/13qznnf/weird_registry_permissions_issue/
That means RegEdit takes care of elevating privileges automatically, behind the scenes.
But Powershell does not. So the attemp to access the remote computer’s Registry directly presented two problems:
- While the reading of of a Value’s data was possible, the payload was different (i.e. wrong) when compared with RegEdit (and that was also obvious, because the behavior of the computer represented what RegEdit showedd, and not what Powershell returned).
- Trying to change the payload via
Set-ItemProperty
failed with “Requested registry access is not allowed”.
That means, with Powershell, oneself has to take care of getting the elevated privileges to be able to do the same work as one could with RegEdit (given that your user account has indeed these rights for the remote computer…).
Two common approaches for that:
- Either start a new Powershell with elevated privileges (“Run as administrator…”).
- Or get elevated privileges by Powershell code: Establish a new PSSession to the remote clients with your credentials (with should give you the elevated privileges), and then do the actual work from within the ScriptBlock of a call to Invoke-Command for that newly created session.
Here’s a short and simple example for the second approach:
$Key = "HKLM:\Software\Microsoft\Windows\CurrentVersion\Policies\System\"
$Value = "DontDisplayLockedUserId"
$Cred = Get-Credential -UserName $(whoami) -Message "Please enter your password"
# Create a new session to the remote computer (with elevated privileges, if the user account has the permissions):
$Session = New-PSSession –ComputerName "client123.example.net" -Credential $Cred
# Run code on the remote client (with hopefully elevated privileges):
Invoke-Command –Session $Session –ScriptBlock {
"$Value is currently set to {0}" -f (Get-ItemPropertyValue $Key -Name $Value)
Set-ItemProperty $Key -Name $Value -Value 1
"$Value is now set to {0}" -f (Get-ItemPropertyValue $Key -Name $Value)
}
Film & Television (54)
How To (63)
Journal (17)
Miscellaneous (4)
News & Announcements (21)
On Software (12)
Projects (26)