
Even though PowerShell contains everything to read and write to the registry I still find myself quite frequently opening the registry editor (aka regedit.exe). Since navigating the tree manually can be quite time consuming I used to rely on RegJump developed by Mark Russinovich.
I was wondering if the same could be implemented using PowerShell and maybe even adding some features like opening multiple registry keys either from the clipboard or provided as an argument to the function.
Say hello to Open-Registry alias regJump. The function opens (instances of) the registry editor for provided paths from the clipboard or as argument to the regKey parameter. The registry paths can contain hive name shortnames like HKLM, HKCU, HKCR or PowerShell provider paths syntax like HKLM:\, HKCU:\.
Similar to how RegJump.exe handles non-existing paths Open-Registry also ignores those parts of the path and works its way backwards until it finds a valid path or returns an error message if the path doesn’t contain any valid parts.
Let’s look at some example use cases:
- Opening multiple instances of regedit at the specified paths via an argument to the regKey paramater:
$testKeys =@' HKLM\Software\Microsoft\Outlook Express HKLM\Software\Microsoft\PowerShell HKLM\Software\Microsoft\Windows '@ -split "`r`n" Open-Registry $testKeys
- Same as above but the keys are no copied to the clipboard instead:
@' HKLM\Software\Microsoft\Outlook Express HKLM\Software\Microsoft\PowerShell HKLM\Software\Microsoft\Windows '@ -split "`r`n" | clip Open-Registry
- The example will open regedit with the run key open as the last part of the path does not represent a key
Open-Registry HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run\Skype
- The example provides an invalid path to the function (using the alias) resulting in a warning message and no instance of regedit opening
regJump HKLMm\xxxxx
Further down below is the source code for the function without comment based help in order to reduce its screen size but the full version can be download from GitHub.
As usual when writing PowerShell I’ve learned one or the other thing along the way. This time I learned how to start a process and wait until its window is visible (this was necessary since otherwise regedit would launch all instances opened on the last path (when multiple paths were passed to the function)):
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| $regeditInstance = [Diagnostics.Process]::Start("regedit","-m") | |
| #wait the regedit window to appear | |
| while ($regeditInstance.MainWindowHandle -eq 0){ | |
| sleep –Milliseconds 100 | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| function Open-Registry{ | |
| [CmdletBinding()] | |
| [Alias("regJump")] | |
| param( | |
| [Parameter(Position=0)] | |
| $regKey | |
| ) | |
| #check for clipbaord only if no argument provided | |
| if (!$regKey){ | |
| #split the clipboard content by crlf and get of trailing crlf in case clipboard populated via piping it to clip.exe | |
| $cmd = { | |
| Add-Type -Assembly PresentationCore | |
| [Windows.Clipboard]::GetText() -split "`r`n" | where {$_} | |
| } | |
| #in case its run from the powershell commandline | |
| if([Threading.Thread]::CurrentThread.GetApartmentState() -eq 'MTA') { | |
| $regKey = & powershell -STA -Command $cmd | |
| } | |
| else { | |
| $regKey = & $cmd | |
| } | |
| } | |
| foreach ($key in $regKey){ | |
| $replacers = @{ | |
| 'HKCU:?\\'='HKEY_CURRENT_USER\' | |
| 'HKLM:?\\'='HKEY_LOCAL_MACHINE\' | |
| 'HKU:?\\'='HKEY_USERS\' | |
| 'HKCC:?\\'='HKEY_CURRENT_CONFIG\' | |
| 'HKCR:?\\'='HKEY_CLASSES_ROOT\' | |
| } | |
| #replace hive shortnames with or without PowerShell Syntax + remove trailing backslash | |
| $properKey = $key | |
| $replacers.GetEnumerator() | foreach { | |
| $properKey = $properKey.ToUpper() -replace $_.Key, $_.Value -replace '\\$' | |
| } | |
| #check if the path points to an existing key or its parent is an existing value | |
| #add one level since we don't want the first iteration of the loop to remove a level | |
| $path = "$properKey\dummyFolder" | |
| #test the registry path and revert to parent path until valid path is found otherwise return $false | |
| while(Split-Path $path -OutVariable path){ | |
| $providerPath = $providerPath = "Registry::$path" | |
| if (Test-Path $providerPath){ | |
| break | |
| } | |
| } | |
| if ($path){ | |
| Set-ItemProperty HKCU:\Software\Microsoft\Windows\CurrentVersion\Applets\Regedit\ -Name LastKey -Value $path -Force | |
| #start regedit using m switch to allow for multiple instances | |
| $regeditInstance = [Diagnostics.Process]::Start("regedit","-m") | |
| #wait the regedit window to appear | |
| while ($regeditInstance.MainWindowHandle -eq 0){ | |
| sleep -Milliseconds 100 | |
| } | |
| } | |
| else{ | |
| Write-Warning "Neither ""$key"" nor any of its parents does exist" | |
| } | |
| } | |
| } | |

Photo Credit: eLKayPics _ off via Compfight cc