Putting Shay's Powershell Registry Functions To Use
Recently I needed to check some registry key values on a bunch of servers. There were far too many servers to make this a manual task and in addition if they weren’t what I was expecting then I needed to change them.
Shay Levy has very helpfully published a Stand Alone Registry Functions Library which I made use of. It allows you to query and set registry values for things such as DWords, Strings, Binary Values on remote machines very easily. In my case I was particularly interested in some configuration settings for the ICA protocol, HKLM\System\CurrentControlSet\Control\Terminal Server\WinStations\ICA-tcp, all of them DWords.
First of all we use Shay’s Get-RegDWord function at the top of the script which contains some .NET code to query a remote registry
function Get-RegDWord{param( [string]$server = “.”, [string]$hive, [string]$keyName, [string]$valueName, [object]$defaultValue=“Your default value”) $hives = [enum]::getnames([Microsoft.Win32.RegistryHive]) if($hives -notcontains $hive){ write-error “Invalid hive value”; return;}$regHive = [Microsoft.Win32.RegistryHive]$hive;$regKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($regHive,$server);$subKey = $regKey.OpenSubKey($keyName); if(!$subKey){ write-error “The specified registry key does not exist.”; return;}$subKey.GetValue($valueName,$defaultValue);}
Then we specify the list of servers to query. You could either use something like:
$servers = Get-Content servers.txt
or in my case they were all virtual servers in VMware so I used a couple of VI Toolkit commands to specify the list
Connect to Virtual CenterConnect-VIServer vc # Get a list of all the powered on servers$servers = Get-Folder ‘Servers’ | Get-VM | Where-Object {$_.Powerstate -eq ‘PoweredOn’}
Then we loop through each server, call Shay’s Get-RegDWord function for each of the DWords we are interested in and store the results in the $myCOl variable. At the end we export the $myCol variable into a CSV file for handy viewing.
Create an empty array to store the results in$myCol = @() foreach ($server in $servers){ $hive = ‘LocalMachine’ $keyname = ‘System\CurrentControlSet\Control\Terminal Server\WinStations\ICA-tcp’ # Find MaxIdleTime $valuename = ‘MaxIdleTime’ $MaxIdleTime = Get-RegDWord $server $hive $keyName $valueName # Find fInheritMaxIdleTime $valueName = ‘fInheritMaxIdleTime’ $fInheritMaxIdleTime = Get-RegDWord $server $hive $keyName $valueName # Find MaxDisconnectionTime $valueName = ‘MaxDisconnectionTime’ $MaxDisconnectionTime = Get-RegDWord $server $hive $keyName $valueName # Find fInheritMaxDisconnectionTime $valueName = ‘fInheritMaxDisconnectionTime’ $fInheritMaxDisconnectionTime = Get-RegDWord $server $hive $keyName $valueName # Add the results to the $MYInfo variable, then $myCol $MYInfo = "" | select-Object Name,MaxIdleTime,fInheritMaxIdleTime,MaxDisconnectionTime,fInheritMaxDisconnectionTime $MYInfo.Name = $server $MYInfo.MaxIdleTime = $MaxIdleTime $MYInfo.fInheritMaxIdleTime = $fInheritMaxIdleTime $MYInfo.MaxDisconnectionTime = $MaxDisconnectionTime $MYInfo.fInheritMaxDisconnectionTime = $fInheritMaxDisconnectionTime $myCol += $MYInfo } # Export the results to a csv file$myCol | Export-Csv citrixservers.csv -NoTypeInformation
Now that we can view the results I was able to see that I needed to set a lot of these values to something new. Using Shay’s Set-RegDWord function it is a pretty straightfoward task to extend the above to do that. First of all add the function to the top of the script.
function Set-RegDWord{ param( [string]$server = “.”, [string]$hive, [string]$keyName, [string]$valueName, [double]$value ) $hives = [enum]::getnames([Microsoft.Win32.RegistryHive]) if($hives -notcontains $hive){ write-error “Invalid hive value”; return; } $regHive = [Microsoft.Win32.RegistryHive]$hive; $regKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($regHive,$server); $subKey = $regKey.OpenSubKey($keyName,$true); if(!$subKey){ write-error “The specified registry key does not exist.”; return; } $subKey.SetValue($valueName, $value,[Microsoft.Win32.RegistryValueKind]::DWord); if($?) {$true} else {$false}}
Then for each of the values you want to change use an if statement to check whether it needs changing and if so call Shay’s Set-RegDword to make the necessary changes.
Find fInheritMaxIdleTime $valueName = ‘fInheritMaxIdleTime’ $fInheritMaxIdleTime = Get-RegDWord $server $hive $keyName $valueName # Check the value and change if necessary if ($fInheritMaxIdleTime -eq 1){ $value = ‘0’ Set-RegDWord $server $hive $keyName $valueName $value }
Thanks again to Shay for publishing these functions, it made this particular task very easy to complete and I’m sure I’ll be using them again in the future.