Contents

Finding remote registry entries with Remoting disabled…


Contents

I had run into a situation where I quickly needed to check registry entries for various machines, but PowerShell remoting had not properly been enabled for all of the machines [and was not allowed to be set up on short notice].

Since I needed to quickly obtain the information for various keys, I turned to Google for advice.

Local and Remote

Firstly I’ll define the registry keys I’d like to have information about:

1
2
3
4
5
$RegKey1 = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Citrix Desktop Delivery Controller'
$Value1 = 'DisplayVersion'

$RegKey2 = 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\7-Zip'
$Value2 = 'DisplayName'

So normally you can get the Local information using the following code:

1
2
(Get-ItemProperty -Path $RegKey1 -Name $Value1).$Value1
(Get-ItemProperty -Path $RegKey2 -Name $Value2).$Value2

If you want to obtain the information Remotely, try the following:

1
2
3
4
5
6
7
8
$Computers = 'localhost',"$env:COMPUTERNAME"

Invoke-Command -ComputerName $Computers -ScriptBlock {
    [PSCustomObject]@{
    Key1 = (Get-ItemProperty -Path $using:RegKey1 -Name $using:Value1).$using:Value1
    Key2 = (Get-ItemProperty -Path $using:RegKey2 -Name $using:Value2).$using:Value2
    }
} | Select-Object PSComputerName,Key1,Key2

As you can see, I can’t just use the variables provided locally, but since I’m running an up-to-date version of PowerShell [v3+], I can using the Using scope modifier, as described here.

I’ve also quickly created a PSCustomObject to contain all the information I require, so I can output this in a clean way.

But what if Remoting is not enabled?

Have no fear, you can still use PowerShell to access the data you want, just through an alternative means.

In this situation, PowerShell can use the power of .NET to still get what it wants! Do note that this does require the Remote Registry Service to be running on the machine.

Firstly, because of the way registry keys are interpreted through the .NET class, this means splitting up our $RegKey1 and $RegKey2 value into a $Hive [since both are in HKLM] and $Key values:

1
2
3
$Hive = 'LocalMachine'
$Key1 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Citrix Desktop Delivery Controller'
$Key2 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\7-Zip'

Using the Microsoft.Win32.RegistryKey class provided by .NET, you can open up a remote connection to a specific hive [LocalMachine, Users] on a remote machine  [you can see this method and other methods available to perform various tasks here].

1
$RemoteReg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($Hive,$Computer)

Once you’ve defined the remote registry connection, you can start getting the information you require using the OpenSubKey and GetValue methods.

1
2
$RegKey1 = $RemoteReg.OpenSubKey($Key1)
$Info1 = $RegKey1.GetValue($Value1)

What does this look like as a final result:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$Computers = 'localhost',"$env:COMPUTERNAME"

$Hive = 'LocalMachine'
$Key1 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Citrix Desktop Delivery Controller'
$Key2 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\7-Zip'

$Array = New-Object System.Collections.ArrayList
foreach ($Computer in $Computers){
	$RemoteReg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($Hive,$Computer)

	$RegKey1 = $RemoteReg.OpenSubKey($Key1)
	$Info1 = $RegKey1.GetValue($Value1)

	$RegKey2 = $RemoteReg.OpenSubKey($Key2)
	$Info2 = $RegKey2.GetValue($Value2)

	$CollectedInfo = [PSCustomObject]@{
		ComputerName = $Computer
		Key1 = $Info1
		Key2 = $Info2
	}
	[void]$Array.Add($CollectedInfo
}
$Array

Hopefuly this can help you in a situation where you just NEED to view remote registry entries, but PowerShell Remoting isn’t [fully] configured.

Happy scripting! 🙂