As the configuration store for the vast majority of applications, the registry plays a central role in system administration. It is also generally hard to manage.
Although command-line tools (such as
reg.exe
) exist to help you work with the registry,
their interfaces are usually inconsistent and confusing. The Registry
Editor graphical user interface is easy to use, but it does not support
scripted administration.
PowerShell tackles this problem by exposing the Windows Registry as a navigation provider: a data source that you navigate and manage in exactly the same way that you work with the filesystem.
Use the Set-Location
cmdlet to
navigate the registry, just as you would navigate the filesystem:
PS > Set-Location HKCU: PS > Set-Location SoftwareMicrosoftWindowsCurrentVersionRun PS > Get-Location Path ---- HKCU:SoftwareMicrosoftWindowsCurrentVersionRun
PowerShell lets you navigate the Windows
Registry in exactly the same way that you navigate the filesystem,
certificate drives, and other navigation-based providers. Like these
other providers, the registry provider supports the Set-Location
cmdlet (with the standard aliases
of sl
, cd
, and chdir
), Push-Location
(with the standard alias
pushd
), Pop-Location
(with the standard alias popd
), and more.
For information about how to change registry
keys once you get to a registry location, see Modify or Remove a Registry Key Value. For more information
about the registry provider, type Get-Help
Registry
.
To retrieve the value(s) of a registry key,
use the Get-ItemProperty
cmdlet, as shown in Example 21-1.
Example 21-1. Retrieving properties of a registry key
PS > Set-Location HKCU: PS > Set-Location SoftwareMicrosoftWindowsCurrentVersionRun PS > Get-ItemProperty . PSPath : Microsoft.PowerShell.CoreRegistry::HKEY_CURRENT_U SERSoftwareMicrosoftWindowsCurrentVersionRun PSParentPath : Microsoft.PowerShell.CoreRegistry::HKEY_CURRENT_U SERSoftwareMicrosoftWindowsCurrentVersion PSChildName : Run PSDrive : HKCU PSProvider : Microsoft.PowerShell.CoreRegistry FolderShare : "C:Program FilesFolderShareFolderShare.exe" / background TaskSwitchXP : d:lee oolsTaskSwitchXP.exe ctfmon.exe : C:WINDOWSsystem32ctfmon.exe Ditto : C:Program FilesDittoDitto.exe QuickTime Task : "C:Program FilesQuickTime Alternativeqttask.exe " -atboottime H/PC Connection Agent : "C:Program FilesMicrosoft ActiveSyncwcescomm.exe"
In the registry provider, PowerShell treats
registry keys as items and key values as properties of those items. To
get the properties of an item, use the Get-ItemProperty
cmdlet. The Get-ItemProperty
cmdlet has the standard alias
gp
.
Example 21-1 lists all property values associated with that specific key. To retrieve the value of a specific item, access it as you would access a property on a .NET object, or anywhere else in PowerShell:
PS > $item = Get-ItemProperty . PS > $item.TaskSwitchXp d:lee oolsTaskSwitchXP.exe
If you want to do this all at once, the command looks like:
PS > $runKey = "HKCU:SoftwareMicrosoftWindowsCurrentVersionRun" PS > (Get-ItemProperty $runKey).TaskSwitchXp d:lee oolsTaskSwitchXP.exe
For more information about the Get-ItemProperty
cmdlet, type Get-
Help
Get-ItemProperty
. For more information about the
registry provider, type Get-Help
Registry
.
To set the value of a registry key, use the
Set-ItemProperty
cmdlet:
PS > (Get-ItemProperty .).MyProgram c: empMyProgram.exe PS > Set-ItemProperty . MyProgram d:Lee oolsMyProgram.exe PS > (Get-ItemProperty .).MyProgram d:Lee oolsMyProgram.exe
To remove the value of a registry key, use the
Remove-ItemProperty
cmdlet:
PS > Remove-ItemProperty . MyProgram PS > (Get-ItemProperty .).MyProgram
In the registry provider, PowerShell treats
registry keys as items and key values as properties of those items. To
change the value of a key property, use the Set-ItemProperty
cmdlet. The Set-ItemProperty
cmdlet has the standard alias
sp
. To remove a key property
altogether, use the Remove-ItemProperty
cmdlet.
As always, use caution when changing information in the registry. Deleting or changing the wrong item can easily render your system unbootable.
For more information about the Get-ItemProperty
cmdlet, type Get-
Help
Get-
ItemProperty
.
For information about the Set-ItemProperty
and Remove-
Item
Property
cmdlets, type Get-Help Set-ItemProperty
or
Get-Help
Remove-
Item
Property
, respectively. For more
information about the registry provider, type Get-Help Registry
.
To add a value to a registry key, use the
New-ItemProperty
cmdlet. Example 21-2 adds
MyProgram.exe to the list of programs that start
when the current user logs in.
Example 21-2. Creating new properties on a registry key
PS > Set-Location HKCU:SoftwareMicrosoftWindowsCurrentVersionRun PS > New-ItemProperty . -Name MyProgram -Value c: empMyProgram.exe PSPath : Microsoft.PowerShell.CoreRegistry::HKEY_CURRENT_USER SoftwareMicrosoftWindowsCurrentVersionRun PSParentPath : Microsoft.PowerShell.CoreRegistry::HKEY_CURRENT_USER SoftwareMicrosoftWindowsCurrentVersion PSChildName : Run PSDrive : HKCU PSProvider : Microsoft.PowerShell.CoreRegistry MyProgram : c: empMyProgram.exe PS > Get-ItemProperty . PSPath : Microsoft.PowerShell.CoreRegistry::HKEY_CURRENT_ USERSoftwareMicrosoftWindowsCurrentVersionRun PSParentPath : Microsoft.PowerShell.CoreRegistry::HKEY_CURRENT_ USERSoftwareMicrosoftWindowsCurrentVersion PSChildName : Run PSDrive : HKCU PSProvider : Microsoft.PowerShell.CoreRegistry FolderShare : "C:Program FilesFolderShareFolderShare.exe" /background TaskSwitchXP : d:lee oolsTaskSwitchXP.exe ctfmon.exe : C:WINDOWSsystem32ctfmon.exe Ditto : C:Program FilesDittoDitto.exe QuickTime Task : "C:Program FilesQuickTime Alternativeqttask.exe" -atboottime H/PC Connection Agent : "C:Program FilesMicrosoft ActiveSyncwcescomm.exe" MyProgram : c: empMyProgram.exe
In the registry provider, PowerShell treats
registry keys as items and key values as properties of those items. To
create a key property, use the New-ItemProperty
cmdlet.
For more information about the New-ItemProperty
cmdlet, type Get-
Help
New-ItemProperty
. For more information about the
registry provider, type Get-Help
Registry
.
To remove a registry key, use the Remove-Item
cmdlet:
PS > dir Hive: HKEY_CURRENT_USERSoftwareMicrosoftWindowsCurrentVersionRun SKC VC Name Property --- -- ---- -------- 0 0 Spyware {} PS > Remove-Item Spyware
As mentioned in Create a Registry Key Value, the registry provider lets you
remove items and containers with the Remove-Item
cmdlet. The Remove-Item
cmdlet has the standard aliases
rm
, rmdir
, del
,
erase
, and rd
.
As always, use caution when changing information in the registry. Deleting or changing the wrong item can easily render your system unbootable.
As in the filesystem, the Remove-Item
cmdlet lets you specify multiple
files through its Path
, Include
, Exclude
, and Filter
parameters. For information on how to
use these parameters effectively, see Find Files That Match a Pattern.
For more information about the Remove-Item
cmdlet, type Get-Help Remove-Item
. For more information
about the registry provider, type Get-Help
Registry
.
You have several related registry modifications, and you want to group them so that either they all apply or none apply.
Use the Start-Transaction
cmdlet to start a
transaction, and make your registry modifications within it. Use the
Complete-Transaction
cmdlet to make the
registry modifications permanent:
PS > Set-Location HKCU: PS > Start-Transaction Suggestion [1,Transactions]: Once a transaction is started, only commands that get called with the -UseTransaction flag become part of that transaction. PS > mkdir TempKey -UseTransaction Hive: HKEY_CURRENT_USER SKC VC Name Property --- -- ---- -------- 0 0 TempKey {} PS > Set-Location TempKey -UseTransaction PS > New-Item TempKey2 -UseTransaction Hive: HKEY_CURRENT_USERTempKey SKC VC Name Property --- -- ---- -------- 0 0 TempKey2 {} PS > Set-Location PS > Get-ChildItem TempKey Get-ChildItem : Cannot find path 'HKEY_CURRENT_USERTempKey' because it does not exist. At line:1 char:14 + Get-ChildItem <<<< TempKey + CategoryInfo : ObjectNotFound: (HKEY_CURRENT_USERTempKey: String) [Get-ChildItem], ItemNotFoundException + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands. GetChildItemCommand PS > Complete-Transaction PS > Get-ChildItem TempKey Hive: HKEY_CURRENT_USERTempKey SKC VC Name Property --- -- ---- -------- 0 0 TempKey2 {}
When working in the registry, you might sometimes want to chain a set of related changes and be sure that they all get applied as a single unit. These are goals known as atomicity and consistency: the desire to avoid situations where an error during any step of the operation could cause an inconsistent system state if the other operations are not also successful.
To support this type of management task, PowerShell supports a change management strategy known as transactions. On Windows Vista and later, PowerShell’s registry provider fully supports transactions.
When you start a transaction, any commands in that transaction are virtual and don’t actually apply to the system until you complete the transaction. Within the context of the transaction, through, each participating command sees the system as though the state really had changed. Once you complete a transaction, changes are applied as a single unit.
Some systems that support transactions (such as databases) put locks on any resources that are being changed by a transaction. If another user tries to modify the locked resources, the user gets an error message. This is not supported in the Windows Registry. If something alters a resource that your transaction depends on, the changes contained in your transaction will be abandoned and you will receive an error message when you try to complete that transaction.
For more information about transactions, see Chapter 30.
To create the registry keys and properties
required to add a site to a specific security zone, use the New-Item
and New-ItemProperty
cmdlets. Example 21-3
adds www.example.com
to the list of
sites trusted by Internet Explorer.
One task that requires modifying data in the registry is working with Internet Explorer to add and remove sites from its different security zones.
Internet Explorer stores its zone mapping
information in the registry at
HKCU:SoftwareMicrosoftWindowsCurrentVersionInternet
SettingsoneMapDomains. Below that key, Explorer stores the
domain name (such as leeholmes.com
)
with the hostname (such as www
) as a
subkey of that one (see Figure 21-1). In the host key,
Explorer stores a property (such as http
) with a DWORD
value that corresponds to the zone
identifier.
The Internet Explorer zone identifiers are:
My Computer
Local intranet
Trusted sites
Internet
Restricted sites
When Internet Explorer is configured in its
Enhanced Security Configuration mode, you must also update
entries under the EscDomains
key.
Once a machine has enabled Internet Explorer’s Enhanced Security Configuration, those settings persist even after removing Enhanced Security Configuration. The following commands let your machine trust UNC paths again:
Set-Location "HKCU:SoftwareMicrosoftWindows" Set-Location "CurrentVersion" Set-Location "Internet Settings" Set-ItemProperty ZoneMap UNCAsIntranet -Type DWORD 1 Set-ItemProperty ZoneMap IntranetName -Type DWORD 1
To remove the zone mapping for a specific
domain, use the Remove-Item
cmdlet:
PS > Get-ChildItem Hive: HKEY_CURRENT_USERSoftware…Internet SettingsoneMapDomains SKC VC Name Property --- -- ---- -------- 1 0 example.com {} PS > Remove-Item -Recurse example.com PS > Get-ChildItem PS >
For more information about using the Internet Explorer registry entries to configure security zones, see the Microsoft KB article “Description of Internet Explorer Security Zones Registry Entries” at http://support.microsoft.com/kb/182569. For more information about managing Internet Explorer’s Enhanced Security Configuration, search for it on http://technet.microsoft.com.
For more information about modifying data in the registry, see Modify or Remove a Registry Key Value.
To modify the Internet Explorer configuration
registry keys, use the Set-
Item
Property
cmdlet. For example, to update
the proxy:
Set-Location "HKCU:SoftwareMicrosoftWindowsCurrentVersionInternet Settings" Set-ItemProperty . -Name ProxyServer -Value http://proxy.example.com Set-ItemProperty . -Name ProxyEnable -Value 1
Internet Explorer stores its main
configuration information as properties on the registry key
HKCU:SoftwareMicrosoftWindowsCurrentVersionInternet
Settings. To change these properties, use the Set-ItemProperty
cmdlet as demonstrated in the
solution.
Another common set of properties to tweak are the configuration parameters that define a security zone. An example of this is to prevent scripts from running in the Restricted Sites zone. For each zone, Internet Explorer stores this information as properties of the registry key HKCU:SoftwareMicrosoftWindowsCurrentVersionInternet Settingsones<Zone>, where <Zone> represents the zone identifier (0, 1, 2, 3, or 4) to manage.
The Internet Explorer zone identifiers are:
My Computer
Local intranet
Trusted sites
Internet
Restricted sites
The names of the properties in this key are not designed for human consumption, as they carry illuminating titles such as 1A04 and 1809. While they are not well-named, you can still script them.
For more information about using the Internet Explorer registry settings to configure security zones, see the Microsoft KB article “Description of Internet Explorer Security Zones Registry Entries” at http://support.microsoft.com/kb/182569.
For more information about modifying data in the registry, see Modify or Remove a Registry Key Value.
Although the Windows Registry Editor is useful for searching the registry, sometimes it might not provide the power you need. For example, the registry editor does not support searches with wildcards or regular expressions.
In the filesystem, we have the Select-String
cmdlet to
search files for content. PowerShell does not offer that ability for other
stores, but we can write a script to do it. The key here is to think of
registry key values like you think of content in a file:
Example 21-4 goes through all registry keys (and their values) for a search term and returns information about the match.
Example 21-4. Search-Registry.ps1
############################################################################## ## ## Search-Registry ## ## From Windows PowerShell Cookbook (O'Reilly) ## by Lee Holmes (http://www.leeholmes.com/guide) ## ############################################################################## <# .SYNOPSIS Search the registry for keys or properties that match a specific value. .EXAMPLE PS >Set-Location HKCU:SoftwareMicrosoft PS >Search-Registry Run #> param( ## The text to search for [Parameter(Mandatory = $true)] [string] $Pattern ) Set-StrictMode -Off ## Helper function to create a new object that represents ## a registry match from this script function New-RegistryMatch { param( $matchType, $keyName, $propertyName, $line ) $registryMatch = New-Object PsObject -Property @{ MatchType = $matchType; KeyName = $keyName; PropertyName = $propertyName; Line = $line } $registryMatch } ## Go through each item in the registry foreach($item in Get-ChildItem -Recurse -ErrorAction SilentlyContinue) { ## Check if the key name matches if($item.Name -match $pattern) { New-RegistryMatch "Key" $item.Name $null $item.Name } ## Check if a key property matches foreach($property in (Get-ItemProperty $item.PsPath).PsObject.Properties) { ## Skip the property if it was one PowerShell added if(($property.Name -eq "PSPath") -or ($property.Name -eq "PSChildName")) { continue } ## Search the text of the property $propertyText = "$($property.Name)=$($property.Value)" if($propertyText -match $pattern) { New-RegistryMatch "Property" $item.Name ` property.Name $propertyText } } }
For more information about running scripts, see Run Programs, Scripts, and Existing Tools.
To retrieve the ACL of a registry key, use the Get-Acl
cmdlet:
PS > Get-Acl HKLM:Software Path Owner Access ---- ----- ------ Microsoft.PowerShell.... BUILTINAdministrators CREATOR OWNER Allow ....
As mentioned in Get the ACL of a File or Directory, the Get-Acl
cmdlet retrieves the security
descriptor of an item. This cmdlet doesn’t work against only the
registry, however. Any provider (for example, the filesystem provider)
that supports the concept of security descriptors also supports the
Get-Acl
cmdlet.
The Get-Acl
cmdlet returns an object that represents the security descriptor of the
item and is specific to the provider that contains the item. In the
registry provider, this returns a .NET System.Security.AccessControl.RegistrySecurity
object that you can explore for further information. For an example of
changing the ACL of a registry key with this result, see Set the ACL of a Registry Key. For an example of a script
that works with ACLs, see Get the ACL of a File or Directory.
For more information about the Get-Acl
command, type Get-Help Get-Acl
. For more information about
working with classes from the .NET Framework, see Work with .NET Objects.
To set the ACL on a registry key, use the
Set-Acl
cmdlet. This
example grants an account write access to a registry key under
HKLM:Software. This is especially useful for
programs that write to administrator-only regions of the registry, which
prevents them from running under a nonadministrator account.
############################################################################## ## ## Grant-RegistryAccessFullControl ## ## From Windows PowerShell Cookbook (O'Reilly) ## by Lee Holmes (http://www.leeholmes.com/guide) ## ############################################################################## <# .SYNOPSIS Grants full control access to a user for the specified registry key. .EXAMPLE PS >$registryPath = "HKLM:SoftwareMyProgram" PS >Grant-RegistryAccessFullControl "LEE-DESKLEE" $registryPath #> param( ## The user to grant full control [Parameter(Mandatory = $true)] $User, ## The registry path that should have its permissions modified [Parameter(Mandatory = $true)] $RegistryPath ) Set-StrictMode -Version Latest Push-Location Set-Location -LiteralPath $registryPath ## Retrieve the ACL from the registry key $acl = Get-Acl . ## Prepare the access rule, and set the access rule $arguments = $user,"FullControl","Allow" $accessRule = New-Object Security.AccessControl.RegistryAccessRule $arguments $acl.SetAccessRule($accessRule) ## Apply the modified ACL to the registry key $acl | Set-Acl . Pop-Location
As mentioned in Set the ACL of a File or Directory, the Set-Acl
cmdlet sets the security descriptor of
an item. This cmdlet doesn’t work against only the registry, however.
Any provider (for example, the filesystem provider) that supports the
concept of security descriptors also supports the Set-Acl
cmdlet.
The Set-Acl
cmdlet requires that you provide it with an ACL to apply to the item.
Although it is possible to construct the ACL from scratch, it is usually
easiest to retrieve it from the item beforehand (as demonstrated in the
Solution). To retrieve the ACL, use the Get-Acl
cmdlet. Once you’ve modified the
access control rules on the ACL, simply pipe them to the Set-Acl
cmdlet to make them permanent.
In the solution, the $arguments
list that we provide to the
RegistryAccessRule
constructor
explicitly sets an Allow
rule on the
Lee
account of the LEE-DESK
computer for FullControl
permission. For more information
about working with classes from the .NET Framework (such as the RegistryAccessRule
class), see Work with .NET Objects.
Although the Set-Acl
command is powerful, you may already
be familiar with command-line
tools that offer similar functionality (such as
SubInAcl.exe
). You can of course continue to use
these tools from PowerShell.
For more information about the Set-Acl
cmdlet, type Get-Help Set-Acl
. For more information about
the Get-Acl
cmdlet, see Get the ACL of a Registry Key.
To work with the registry of a remote
computer, use the scripts provided in this chapter: Get-RemoteRegistryChildItem
(Program: Get Registry Items from Remote Machines), Get-RemoteRegistryKeyProperty
(Program: Get Properties of Remote Registry Keys), and
Set-RemoteRegistryKeyProperty
(Program: Set Properties of Remote Registry Keys). These scripts
require that the remote computer has the remote registry service enabled
and running. Example 21-5
updates the PowerShell execution policy of a remote machine.
Example 21-5. Setting the PowerShell execution policy of a remote machine
PS > $registryPath = "HKLM:SoftwareMicrosoftPowerShell1" PS > Get-RemoteRegistryChildItem LEE-DESK $registryPath SKC VC Name Property --- -- ---- -------- 0 1 1033 {Install} 0 5 PowerShellEngine {ApplicationBase, ConsoleHostAss... 2 0 PowerShellSnapIns {} 1 0 ShellIds {} PS > Get-RemoteRegistryChildItem LEE-DESK $registryPathShellIds SKC VC Name Property --- -- ---- -------- 0 2 Microsoft.PowerShell {Path, ExecutionPolicy} PS > $registryPath = "HKLM:SoftwareMicrosoftPowerShell1" + "ShellIdsMicrosoft.PowerShell" PS > Get-RemoteRegistryKeyProperty LEE-DESK $registryPath ExecutionPolicy ExecutionPolicy --------------- Unrestricted PS > Set-RemoteRegistryKeyProperty LEE-DESK $registryPath ` "ExecutionPolicy" "RemoteSigned" PS > Get-RemoteRegistryKeyProperty LEE-DESK $registryPath ExecutionPolicy ExecutionPolicy --------------- RemoteSigned
Although this specific task is perhaps better solved through PowerShell’s Group Policy support, it demonstrates a useful scenario that includes both remote registry exploration and modification.
If the remote computer does not have the Remote Registry service
running (but does have WMI enabled), you can use WMI’s
StdRegProv
class to work with the registry as well.
The following example demonstrates how to get and set the registry key
that controls Remote Desktop:
$HKEY_CLASSES_ROOT = [Convert]::ToUInt32(80000000, 16) $HKEY_CURRENT_USER = [Convert]::ToUInt32(80000001, 16) $HKEY_LOCAL_MACHINE = [Convert]::ToUInt32(80000002, 16) $HKEY_USERS = [Convert]::ToUInt32(80000003, 16) $HKEY_CURRENT_CONFIG = [Convert]::ToUInt32(80000005, 16) ## Connect to the registry via WMI $reg = Get-WmiObject -ComputerName LEE-DESK ` -Namespace rootdefault StdRegProv -List ## Get and set DWORD values on the remote machine $reg.GetDWORDValue($HKEY_LOCAL_MACHINE, "SYSTEMCurrentControlSetControlTerminal Server", "fDenyTSConnections") $reg.SetDWORDValue($HKEY_LOCAL_MACHINE, "SYSTEMCurrentControlSetControlTerminal Server", "fDenyTSConnections", 0)
For more information about the
Get-RemoteRegistryChildItem
, Get-RemoteRegistryKeyProperty
, and Set-RemoteRegistryKeyProperty
scripts, see
Recipes , , and .
Although PowerShell does not directly let you access and manipulate the registry of a remote computer, it still supports this by working with the .NET Framework. The functionality exposed by the .NET Framework is a bit more developer-oriented than we want, so we can instead use a script to make it easier to work with.
Example 21-6 lets you list child items in a remote registry key, much like you do on the local computer. In order for this script to succeed, the target computer must have the remote registry service enabled and running.
Example 21-6. Get-RemoteRegistryChildItem.ps1
############################################################################## ## ## Get-RemoteRegistryChildItem ## ## From Windows PowerShell Cookbook (O'Reilly) ## by Lee Holmes (http://www.leeholmes.com/guide) ## ############################################################################## <# .SYNOPSIS Get the list of subkeys below a given key on a remote computer. .EXAMPLE Get-RemoteRegistryChildItem LEE-DESK HKLM:Software #> param( ## The computer that you wish to connect to [Parameter(Mandatory = $true)] $ComputerName, ## The path to the registry items to retrieve [Parameter(Mandatory = $true)] $Path ) Set-StrictMode -Version Latest ## Validate and extract out the registry key if($path -match "^HKLM:\(.*)") { $baseKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey( "LocalMachine", $computername) } elseif($path -match "^HKCU:\(.*)") { $baseKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey( "CurrentUser", $computername) } else { Write-Error ("Please specify a fully-qualified registry path " + "(i.e.: HKLM:Software) of the registry key to open.") return } ## Open the key $key = $baseKey.OpenSubKey($matches[1]) ## Retrieve all of its children foreach($subkeyName in $key.GetSubKeyNames()) { ## Open the subkey $subkey = $key.OpenSubKey($subkeyName) ## Add information so that PowerShell displays this key like regular ## registry key $returnObject = [PsObject] $subKey $returnObject | Add-Member NoteProperty PsChildName $subkeyName $returnObject | Add-Member NoteProperty Property $subkey.GetValueNames() ## Output the key $returnObject ## Close the child key $subkey.Close() } ## Close the key and base keys $key.Close() $baseKey.Close()
For more information about running scripts, see Run Programs, Scripts, and Existing Tools.
Although PowerShell does not directly let you access and manipulate the registry of a remote computer, it still supports this by working with the .NET Framework. The functionality exposed by the .NET Framework is a bit more developer-oriented than we want, so we can instead use a script to make it easier to work with.
Example 21-7 lets you get the properties (or a specific property) from a given remote registry key. In order for this script to succeed, the target computer must have the remote registry service enabled and running.
Example 21-7. Get-RemoteRegistryKeyProperty.ps1
############################################################################## ## ## Get-RemoteRegistryKeyProperty ## ## From Windows PowerShell Cookbook (O'Reilly) ## by Lee Holmes (http://www.leeholmes.com/guide) ## ############################################################################## <# .SYNOPSIS Get the value of a remote registry key property .EXAMPLE PS >$registryPath = "HKLM:softwareMicrosoftPowerShell1ShellIdsMicrosoft.PowerShell" PS >Get-RemoteRegistryKeyProperty LEE-DESK $registryPath ExecutionPolicy #> param( ## The computer that you wish to connect to [Parameter(Mandatory = $true)] $ComputerName, ## The path to the registry item to retrieve [Parameter(Mandatory = $true)] $Path, ## The specific property to retrieve $Property = "*" ) Set-StrictMode -Version Latest ## Validate and extract out the registry key if($path -match "^HKLM:\(.*)") { $baseKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey( "LocalMachine", $computername) } elseif($path -match "^HKCU:\(.*)") { $baseKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey( "CurrentUser", $computername) } else { Write-Error ("Please specify a fully-qualified registry path " + "(i.e.: HKLM:Software) of the registry key to open.") return } ## Open the key $key = $baseKey.OpenSubKey($matches[1]) $returnObject = New-Object PsObject ## Go through each of the properties in the key foreach($keyProperty in $key.GetValueNames()) { ## If the property matches the search term, add it as a ## property to the output if($keyProperty -like $property) { $returnObject | Add-Member NoteProperty $keyProperty $key.GetValue($keyProperty) } } ## Return the resulting object $returnObject ## Close the key and base keys $key.Close() $baseKey.Close()
For more information about running scripts, see Run Programs, Scripts, and Existing Tools.
Although PowerShell does not directly let you access and manipulate the registry of a remote computer, it still supports this by working with the .NET Framework. The functionality exposed by the .NET Framework is a bit more developer-oriented than we want, so we can instead use a script to make it easier to work with.
Example 21-8 lets you set the value of a property on a given remote registry key. In order for this script to succeed, the target computer must have the remote registry service enabled and running.
Example 21-8. Set-RemoteRegistryKeyProperty.ps1
############################################################################## ## ## Set-RemoteRegistryKeyProperty ## ## From Windows PowerShell Cookbook (O'Reilly) ## by Lee Holmes (http://www.leeholmes.com/guide) ## ############################################################################## <# .SYNOPSIS Set the value of a remote registry key property .EXAMPLE PS >$registryPath = "HKLM:softwareMicrosoftPowerShell1ShellIdsMicrosoft.PowerShell" PS >Set-RemoteRegistryKeyProperty LEE-DESK $registryPath ` "ExecutionPolicy" "RemoteSigned" #> param( ## The computer to connect to [Parameter(Mandatory = $true)] $ComputerName, ## The registry path to modify [Parameter(Mandatory = $true)] $Path, ## The property to modify [Parameter(Mandatory = $true)] $PropertyName, ## The value to set on the property [Parameter(Mandatory = $true)] $PropertyValue ) Set-StrictMode -Version Latest ## Validate and extract out the registry key if($path -match "^HKLM:\(.*)") { $baseKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey( "LocalMachine", $computername) } elseif($path -match "^HKCU:\(.*)") { $baseKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey( "CurrentUser", $computername) } else { Write-Error ("Please specify a fully-qualified registry path " + "(i.e.: HKLM:Software) of the registry key to open.") return } ## Open the key and set its value $key = $baseKey.OpenSubKey($matches[1], $true) $key.SetValue($propertyName, $propertyValue) ## Close the key and base keys $key.Close() $baseKey.Close()
For more information about running scripts, see Run Programs, Scripts, and Existing Tools.
You want to automate the configuration of a program, but that program does not document its registry configuration settings.
To discover a registry setting for a program, use the Sysinternals Process Monitor to observe registry access by that program. Process Monitor is available from http://www.microsoft.com/technet/sysinternals/FileAndDisk/processmonitor.mspx.
In an ideal world, all programs would fully support command-line administration and configuration through PowerShell cmdlets. Many programs do not, however, so the solution is to look through their documentation in the hope that they list the registry keys and properties that control their settings. While many programs document their registry configuration settings, many still do not.
Although these programs may not document their registry settings, you can usually observe their registry access activity to determine the registry paths they use. To illustrate this, we will use the Sysinternals Process Monitor to discover PowerShell’s execution policy configuration keys. Although PowerShell documents these keys and makes its automated configuration a breeze, this example illustrates the general technique.
Once you’ve downloaded Process Monitor, the first step is to filter its output to include only the program you are interested in. By default, Process Monitor logs almost all registry and file activity on the system.
First, launch Process Monitor, and then press Ctrl-E (or click the magnifying glass icon) to temporarily prevent it from capturing any data (see Figure 21-2). Next, press Ctrl-X (or click the white sheet with an eraser icon) to clear the extra information that it captured automatically. Finally, drag the target icon and drop it on top of the application in question. You can press Ctrl-L (or click the funnel icon) to see the filter that Process Monitor now applies to its output.
Next, prepare to manually set the program’s
configuration option. Usually, this means typing and clicking all the
property settings, but just not clicking OK or Apply. For this
PowerShell example, type the Set-ExecutionPolicy
command line, but do not
press Enter (see Figure 21-3).
Switch to the Process Monitor window, and then press Ctrl-E (or click the magnifying glass icon). Process Monitor now captures all registry access for the program in question.
Click OK, Apply, or whatever action it takes to actually complete the program’s configuration. For the PowerShell example, this means pressing Enter.
Switch again to the Process Monitor window, and then press Ctrl-E (or click the magnifying glass icon). Process Monitor now no longer captures the application’s activity.
The Process Monitor window now shows all registry keys that the application interacted with when it applied its configuration setting.
Press Ctrl-F (or click the binoculars icon),
and then search for RegSetValue
.
Process Monitor highlights the first modification to a registry key,
as shown in Figure 21-4.
Press Enter (or double-click the highlighted
row) to see the details about this specific registry modification. In
this example, we can see that PowerShell changed the value of the
ExecutionPolicy
property (under
HKLM:SoftwareMicrosoftPowerShell1ShellIdsMicrosoft.PowerShell)
to RemoteSigned
. Press F3 to see
the next entry that corresponds to a registry modification.
Now that you know all registry writes that the application performed when it updated its settings, judgment and experimentation will help you determine which modifications actually represent this setting. Since PowerShell performed only one registry write (to a key that very obviously represents the execution policy), the choice is pretty clear in this example.
Once you’ve discovered the registry keys, properties, and values that the application uses to store its configuration data, you can use the techniques discussed in Modify or Remove a Registry Key Value to automate these configuration settings, as in the following example:
PS > $key = "HKLM:SoftwareMicrosoftPowerShell1" + "ShellIdsMicrosoft.PowerShell" PS > Set-ItemProperty $key ExecutionPolicy AllSigned PS > Get-ExecutionPolicy AllSigned PS > Set-ItemProperty $key ExecutionPolicy RemoteSigned PS > Get-ExecutionPolicy RemoteSigned
18.117.78.237