Querying a Remote Registry
So this week I have been working on a script that will allow me to view the registry on remote machines. While speaking to a colleague about this he already had a script put together, which worked…but what’s the fun in that. So taking a quick look at his code, I pulled the key factor. In .NET there is a class that will allow you to open a remote registry.
[Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]$Hive,$computer)
This allows me to specify the hive and the computer on the network that I want to get values from.
Using Get-Member (one of my favourite commands) I could see there was a “OpenSubKey()” method.
This “OpenSubKey()” method allows you to specify a registry for it to open. There is also a “GetValueNames()” method that returns the keys in the specified registry.
What I wanted to do was to be able to specify a Hive/Registry/Key and for it to spit out the value. I also wanted the script to do was for me to just specify the Hive/Registry and for it to tell me the other “folders” in that registry.
So, this is what I came up with.
Please feel free to use it.
Function Get-RemoteRegKey
{
[OutputType('System.Boolean')]
[CmdletBinding(DefaultParameterSetName = "__AllParameterSets")]
param(
[Parameter(
Position = 0,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true
)]
[Alias("CN","__SERVER","IPAddress")]
[string[]]$ComputerName = "",
[Parameter(
Position = 1,
ValueFromPipelineByPropertyName = $true,
HelpMessage = "The HKEY to open, from the RegistryHive enumeration. The default is 'LocalMachine'.")]
[ValidateSet("ClassesRoot","CurrentUser","LocalMachine","Users","PerformanceData","CurrentConfig","DynData")]
[string]$Hive = "LocalMachine",
[Parameter(
Mandatory = $false,
Position = 2,
ValueFromPipelineByPropertyName = $true,
HelpMessage = "The path of the subkey to open.")]
[string]$reg,
[Parameter(
Mandatory = $false,
Position = 3,
ValueFromPipelineByPropertyName = $true,
HelpMessage = "The name of the value to open.")]
[string[]]$key
)
process
{
foreach($computer in $ComputerName)
{
write-verbose "Opening Remote have to: $Computer into Hive: $Hive"
try
{
$query = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]$Hive,$computer)
}
catch
{
write-error "Error connecting to the remote registry. Please review your computername"
break
}
write-verbose "Opening $reg in $hive"
try
{
$InitialKey = $query.OpenSubKey($reg).getvaluenames()
}
catch
{
write-error "Could not open $hive\$reg - its possible it does not exsist."
break
}
if (!$InitialKey)
{
write-verbose "Could not find any Keys in specified Reg - Returning object with no KeyValues - $($query.opensubkey($reg).name)"
$query_noValue = New-Object pscustomobject
$query_noValue | Add-Member -name Reg -type NoteProperty -Value "$hive\$reg"
$query_noValue | Add-Member -Name SubReg -type NoteProperty -value $query.OpenSubKey("$reg").getsubkeynames()
return $query_noValue
}
if($key)
{
write-verbose "Getting single value $key from $($query.opensubkey($reg).name)"
$query_value = New-Object pscustomobject
$query_value | Add-Member -Name Reg -type NoteProperty -value "$hive\$reg"
$query_value | Add-Member -Name KeyKind -type NoteProperty -Value $query.opensubkey("$reg").getvaluekind($key).tostring()
$query_value | add-member -name Key -type NoteProperty -value "$key"
$query_value | Add-Member -Name KeyValue -type NoteProperty -value $query.opensubkey("$reg").GetValue($key)
$query_value | Add-Member -Name SubReg -type NoteProperty -value $query.OpenSubKey("$reg").getsubkeynames()
return $query_value
}
$query_obj = $null
$query_obj = @{}
$query_Output = $null
$query_Output = @()
write-verbose "Starting loop for all keys in directory $($query.opensubkey($reg).name)"
foreach($s in $InitialKey)
{
$query_obj = New-Object pscustomobject
$query_obj | Add-Member -Name Reg -type NoteProperty -value "$hive\$reg"
$query_obj | Add-Member -Name KeyKind -type NoteProperty -Value $query.opensubkey("$reg").getvaluekind($s).tostring()
$query_obj | add-member -name Key -type NoteProperty -value "$s"
$query_obj | Add-Member -Name KeyValue -type NoteProperty -value $query.opensubkey("$reg").GetValue($s)
$query_obj | Add-Member -Name SubReg -type NoteProperty -value $query.OpenSubKey("$reg").getsubkeynames()
$query_Output += $query_obj
}
}
}
end
{
return $query_Output
}
}
Here is a image of a typical output if you specify all parameters:
Here is a image of a typical output when you do not specify the -Key parameter:
As you can see from the above image, because there are no keys in this Reg it just returns you the sub-folders (I call the subreg in the object)
If you have any questions about this script you can drop me a line on twitter alexinnes