- Add a domain user or group to local administrators with PowerShell - Wed, Mar 19 2014
- Create a list of local administrators with PowerShell - Wed, Mar 5 2014
- Remotely query user profile information with PowerShell - Tue, Nov 26 2013
The Registry is very handy for administrators. For example, if you want to prevent an Outlook plug-in from starting, you can achieve this by setting a registry key. But you can do much more, including manage IE settings, display the installed software, and perform many other administrative tasks. In light of the Registry’s many benefits, I have written a PowerShell script that queries the given registry values from a list of computers.
You can control the script with three parameters. Two of them (RegistryKey and KeyProperty) are mandatory. The third (ComputerName) is optional.
RegistryKey is the path to the registry key where the required registry key properties are located. For example, consider the following registry key:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\AutoAdminLogon.
The key decides if automatic logon is active, and it has two possible values (enabled/disabled). The “HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\” part is the RegistryKey; the remaining part, “AutoAdminLogon,” is the KeyProperty.
If you want to query the value of AutoAdminLogon, you have to submit both parts as parameters to the script. If you want to retrieve the registry key of a remote computer, you also have to provide a value to the –ComputerName parameter. If the parameter is not set, the script will operate on the local computer.
Split the registry key
After processing the parameters, I use a regular expression to separate basekey and subkey. I need both values in my script later. A switch statement processes the basekey value and generates the equivalent string that the [Microsoft.Win32.RegistryKey] class can understand.
$RegistryKey -match "(?\w+)\\(?.+)" | Out-Null switch($Matches.BaseKey) { "HKEY_LOCAL_MACHINE" {$BaseKey = "LocalMachine"} "HKEY_USERS" {$BaseKey = "Users"} "HKEY_CLASSES_ROOT" {$BaseKey = "ClassesRoot"} "HKEY_CURRENT_USER" {$BaseKey = "CurrentUser"} "HKEY_CURRENT_CONFIG" {$BaseKey = "CurrentConfig"} default { write-host "Unable to determine base key type. Exiting" exit(1) } }
Connect to the remote computer and retrieve the key
Now let us enter the main part of the script. This part of the script connects to the remote base registry and navigates to the required sub registry key. I am using the [Microsoft.Win32.RegistryKey] base class for connecting to the remote registry. When the connection initializes, we need to provide two variables: the computer name and the base key (for example, LocalMachine or LocalUser). After connection has been established successfully, we can directly navigate to the sub registry key that stores the value we are looking for. After obtaining the object of the registry subkey, we need to query all the key properties inside the subkey to find out if the key we are querying is present. When it is found, the variable $flag is set to $true and the following code queries the value of the registry key property using the GetValue method. It also determines the type of the key by using the GetValueKind method. The type indicates whether the value is STRING, DWORD, or BINARY.
Once these details are collected, a custom object is created with the properties ComptuerName, PropertyName, PropertyValue, PropertyType, and IsPresent and the values are assigned to these properties accordingly. Though all properties are self-explanatory, I want to specifically mention something about IsPresent; this parameter indicates if the registry key we are querying for is present or not. If the key exists, the other properties of the object are populated with the corresponding values; otherwise, they will be empty.
if(Test-Connection -ComputerName $Computer -count 1 -ea 0) { $flag = $false $BaseKeyObj = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($BaseKey, $computer) $KeyObj = $BaseKeyObj.OpenSubKey($Matches.SubKey) if($KeyObj) { foreach ($Property in $KeyObj.GetValueNames()) { if($KeyProperty -contains $Property) { $flag = $true } } } else { Write-Warning "$($Matches.SubKey) not found on $Computer" } if($flag) { $PropertyType = $KeyObj.GetValueKind($KeyProperty) $PropertyValue = $KeyObj.GetValue($KeyProperty) } $OutputObj = New-Object PSObject -Prop ( @{ ComputerName = $Computer.ToUpper() PropertyName = $KeyProperty PropertyValue = $PropertyValue PropertyType = $PropertyType IsPresent = $flag }) }
At the end of script, I print the custom object we just generated.
If you have a list of remote computers and you want to feed them to the script, you just need to execute the following command:
Get-Content c:\scripts\Computers.txt | .\Get-RemoteRegistry.ps1 -RegistryKey "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -KeyProperty AutoAdminLogon
If you want to send the output of the script to a text file, you need to use the pipe and Out-File as shown below:
Get-Content c:\scripts\Computers.txt | .\Get-RemoteRegistry.ps1 -RegistryKey "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -KeyProperty AutoAdminLogon | Out-File C:\scripts\RegistryKeyOutput.txt
Output of PowerShell script to retrieve a remote registry key
It is simple to get the value of a registry key, but modifying it is more complex. In my next post, I will provide a script that you can use to change the value of a registry key on remote computers. I hope this script is helpful to you, and I hope you enjoy learning PowerShell.
Download the PowerShell script to read registry keys
It’s a great way, but how can I edit Windows Registry?
I found a solution: Remote Registry Manager, a part of AdminToys Suite softwaer.
Ops, my fault ) Awaiting for further articles regarding how to edit the registry… Thanks for a great article!
George, the article regarding how to edit the registry is online now.
https://4sysops.com/archives/create-and-modify-registry-keys-in-remote-computers-using-powershell/
Thanks,
Sitaram
When I use Get-Content and supply my servers.txt file, the script only reads the first line of the file and will not continue to the rest of the list.
Ben, please post the complete command you are using, so that I will be able to comment better.
Ben, I understood where the problem is. I will get it corrected.
Meantime you can use the below to process all computers in servers.txt
get-content c:\servers.txt | % { .\Get-RemoteRegistry.ps1 -ComputerName $_ -RegistryKey “HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon” -KeyProperty AutoAdminLogon | Out-File C:\scripts\RegistryKeyOutput.txt -Append }
Ben, I got the correction made to the script. Try out the latest one by using the download link in the post.
Hey… thanks for the quick turn around! =) That did the trick on your post.
I’ve been playing around with various scripts all morning, but I’d like to be able to share my code with you. My end goal is to be able to query sets of machines for all keys below a reg path and output to CSV for filtering. I have the main part working but I can only send the output to the console. I am having trouble with properly sending to CSV.
Building off poshcode.org/615 – I get-content from servers.txt and want to have a table like the following that has dynamic number of columns depending upon the included registry keys in that path:
Example path = HKLM\SYSTEM\CurrentControlSet\Control\Power\
Example CSV output =
Hostname | Subkeys | CustomizeDuringSetup | HiberFileSize
—————————————————-
server1 | (ListAllSubkeys)| Value1 | Value2
server2 | (subkey1,subkey2…
Hi,
Did you ever get this going, I'm in the same situation, would like to retrieve the TLS 1.2 parameters (HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2) from moultiple servers
and if possible the latest .net version installed?
and output all of this to file, related to each server.
D
Did you able to do it in this way ? I am struggling to get data in table format. current out put of this file is not convenient when working on multiple computer. please let me know if you or someone made it possible.
Thanks for your advice! I posted the similar script to yours here – powershellcommunity.org/Forums/tabid/54/aft/8120/Default.aspx
In case somebody is looking for a way to read default registry values(one looks like (default)in regedit) of a registry key, please take a look at http://techibee.com/powershell/read-remote-registry-key-default-values-using-powershell/1913
Guys:
I know this is an old post but… so I am using powershell with foreach on list of machines and i need to query remote base key on the ones in list. The problem is I want to invoke diffrent credentials for elevated rights.
$Details = @()
$vmCount = 0
$remCreds = Get-Credential -Credential naipaper\ -ErrorAction Stop
foreach ($fieldVc in $fieldVcs)
{
$vmCount++
Write-Host “Getting DB $vmCount for host $($fieldVc.srvName)” -foregroundcolor red -backgroundcolor yellow
$vcdbprops = @{
VC_Name = $fieldVc.srvName
DB_Server = “”
DB_Instance = “”
DSN_Name = “”
}
$props = New-Object psobject -Property $vcdbprops
$hklm = invoke-command [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey(‘LocalMachine’, $fieldVc.srvName) -Credential $remCreds
$vcReg = $hklm.OpenSubKey(“SOFTWARE\\VMware, Inc.\\VMware VirtualCenter”)
$vcRegDB = $hklm.OpenSubKey(“SOFTWARE\\VMware, Inc.\\VMware VirtualCenter\\DB”)
$odbcReg = $hklm.OpenSubKey(“SOFTWARE\\ODBC\\ODBC.INI\\” + $vcRegDB.GetValue(1))
$props.DB_Server = $odbcReg.GetValue(“Server”)
$props.DB_Instance = $vcReg.GetValue(“DBInstanceName”)
$props.DSN_Name = $vcRegDB.GetValue(1)
$Details += $props
Can someone help me to invoke elevated rights in my foreach?
hi,
i need to get the value of “ScreenSaveTimeOut” from the below registry path across multiple computers:
HKCU:\Software\Policies\Microsoft\Windows\Control Panel\Desktop\
can you please help with it?
thanks.
Hey,
You’ve mentioned in your script: “.\Get-RemoteRegistry.ps1″ what’s that and what that script contain??
Works like Charm..Superb Script..Saved My Job. 🙂
Its the name of the powershell script where you will put the above contents and run.
Hello Sitaram,
I ran the script, but I’m getting the following error
PS C:\Script\Registry> Get-Content C:\Script\Registry\Computers.txt | .\Registry.ps1 -RegistryKey “HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters” -KeyProperty SMB1 | Out-File C:\Script\Registry\RegistryKeyOutput.txt
Unable to determine base key type. Exiting
I’m not sure, why the switch is not recording what I’m passing on command. Can you please help.
When I run the following command from my PC, with the downloaded script in the correct location and the computer listed in the provided location, the only output I get in the text file relates to my computername, which isn’t even included in the list.
PS C:\WINDOWS\system32> Get-Content c:\scripts\computers.txt | % {c:\scripts\Get-Registry.ps1 -RegistryKey “HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\SystemCertificates\AuthRoot\” -KeyProperty DisableRootAutoUpdate | Out-file c:\scripts\result.txt -Append}
Did a miss a step, or do something incorrectly?
I dont think this runs with the new powershell 5
@Erwin
This is probably not how we would do it 7 years after this article has been written but it still works with PowerShell 5.1.
it does not i get
IsPresent : False
PropertyType :
ComputerName : *******
PropertyValue :
PropertyName : Shell
Never mind..I am a dunce 🙁
Hi, Will it work in Windows server 2019?.
I am looking for the same script with excel output.
I don’t see any commands that shouldn’t work on Windows Server 2019. Give it a try in a test environment.