Use PowerShell to open regedit at a specific path or RegJump for PowerShell

12206559615_2b81475662_m
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:

  1. 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 
  2. 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 
  3. 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 
  4. 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)):


$regeditInstance = [Diagnostics.Process]::Start("regedit","-m")
#wait the regedit window to appear
while ($regeditInstance.MainWindowHandle -eq 0){
sleep Milliseconds 100
}

view raw

Wait-Window.ps1

hosted with ❤ by GitHub


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"
}
}
}

shareThoughts


Photo Credit: eLKayPics _ off via Compfight cc

I'd love to hear what you think