Monthly Archive



Cleaning up entries on Remote Desktop Connection

I use RDP between my main laptop and the machine on which my lab resides. When I rebuild the lab the entries in the Remote Desktop Connection for the old machine still remain.


There isn’t a direct way to remove those entries. But you can remove them from the registry.


First view the entries

Get-ChildItem -Path 'HKCU:\SOFTWARE\Microsoft\Terminal Server Client\'

    Hive: HKEY_CURRENT_USER\SOFTWARE\Microsoft\Terminal Server Client

Name                           Property
----                           --------
Default                        MRU0 : RSLaptop01
                               MRU1 : serverrs01
                               MRU2 : server02


The partial list above shows you that the property names are MRU* 


You can view individual entries

Get-ItemProperty -Path 'HKCU:\SOFTWARE\Microsoft\Terminal Server Client\Default\' -Name MRU2

MRU2         : server02
PSPath       : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\SOFTWARE\Microsoft\Terminal
               Server Client\Default\
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\SOFTWARE\Microsoft\Terminal
               Server Client
PSChildName  : Default
PSDrive      : HKCU
PSProvider   : Microsoft.PowerShell.Core\Registry


You can now delete as required – for instance


Remove-ItemProperty -Path 'HKCU:\SOFTWARE\Microsoft\Terminal Server Client\Default\' -Name MRU2

Scripting Guy CDXML series

Today starts a four part series I’ve written for the Scripting Guy blog on using CDXML to create a module to work with the registry.  Don’t know what CDXML is – you will when you’ve read the series


The first post is at

When did Windows update last run

A question came up on the forum regarding when Windows Update last run and when an update was last installed.  Get-Hotfix shows the date of installation for most BUT not all patches.

The registry holds values showing last successful detection and install:

$props = [ordered]@{
LastDetect = Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\Results\Detect' -Name LastSuccessTime |
select -ExpandProperty LastSuccessTime

LastInstall = Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\Results\Install' -Name LastSuccessTime |
select -ExpandProperty LastSuccessTime

New-Object -TypeName psobject -Property $props

Registry oddity

Looking at modifying the registry on a virtual machine while its offline. I mount the VHDX file and can run this  to load the registry

PS> reg load HKLM\VHDSYS h:\windows\system32\config\system
The operation completed successfully.

If I perform a reg unload at this point everything works but if I access the registry – for instance

PS> ls hklm:

and then try and unload I get an error!

PS> reg unload HKLM\VHDSYS
ERROR: Access is denied.

One thing I found is that there is as reference to the remote hive in the variable collection

PS> ls variable:

Name                           Value
----                           -----
$                              HKLM\VHDSYS

Empirically I’ve found that running these commands

ls env:
ls variable:

changes the value of the $ variable

You can then unload the hive

PS> reg unload HKLM\VHDSYS
The operation completed successfully.

Decoding the mounted device information

In the previous post we looked at how to read the mounted device information. The data is in binary though – if you want it readable and not all of it is readable – try this

$data = @()            
Get-Item -Path HKLM:\SYSTEM\MountedDevices |            
select -ExpandProperty Property |            
where {$_ -like "\Dos*"} |             
foreach {            
 $name = $_            
 $bin = (Get-ItemProperty -Path HKLM:\SYSTEM\MountedDevices -Name $name)."$name"            
 $decoded = @()            
 $bin | foreach {            
  $decoded += [char]$_            
 $data += New-Object -TypeName psobject -Property @{            
  Device =  $name            
  BinaryValue  = $bin            
  DecodedValue = $($decoded -join "")            
$data | Format-Table  Device, DecodedValue  -AutoSize

Same as last time except for the loop through the binary data using [char] to decode the ASCII values.  use –join to make a string rather than an array. The apparent gaps in the resultant string are because we’re dealing with Unicode

Reading mounted device information from the registry

Interesting question about reading the registry.  How do you read HKLM:\SYSTEM\MountedDevices and pull out the name of the device and the associated data.

Get-Item -Path HKLM:\SYSTEM\MountedDevices

returns data of this form

Name                           Property
----                           --------
MountedDevices                 \DosDevices\C: : {218, 187, 32, 142...}
                               \DosDevices\G: : {92, 0, 63, 0...}
                               \DosDevices\E: : {95, 0, 63, 0...}
                               \DosDevices\F: : {92, 0, 63, 0...}
                               \DosDevices\D: : {218, 187, 32, 142...}
                               \DosDevices\I: : {95, 0, 63, 0...}

We need to drill into the property but if we expand the property we will only get the name of the device. So we need to loop through those names

$data = @()            
Get-Item -Path HKLM:\SYSTEM\MountedDevices |            
select -ExpandProperty Property |            
where {$_ -like "\Dos*"} |             
foreach {            
 $name = $_            
$data += New-Object -TypeName psobject -Property @{            
  Device =  $name             
  Value  = (Get-ItemProperty -Path HKLM:\SYSTEM\MountedDevices -Name $name)."$name"            

To simplify the output is limited to Dos devices

Get-itemproperty returns the data with the name of the device as the property name so we need to drill in to get the value

Set registry key owner

In chapter 7 of PowerShell and WMI I stated that I would post a .NET version of a script to set ownership of a registry key. The WMI method needs Vista or above so we need the .NET version for pre-Vista operating systems.

function set-regkeyowner {            
param (            
 [Validateset(“HKCR”, “HKCU”, “HKLM”, "HKUS", "HKCC")]            
PROCESS {             
Write-Verbose "Set Hive"            
switch ($hive){            
 “HKCR” {$reg = [Microsoft.Win32.Registry]::ClassesRoot}            
 “HKCU” {$reg = [Microsoft.Win32.Registry]::CurrentUser}            
 “HKLM” {$reg = [Microsoft.Win32.Registry]::LocalMachine}            
 "HKUS" {$reg = [Microsoft.Win32.Registry]::Users}            
 "HKCC" {$reg = [Microsoft.Win32.Registry]::CurrentConfig}            
$permchk = [Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree            
$regrights = [System.Security.AccessControl.RegistryRights]::ChangePermissions            
Write-Verbose "Open Key and get access control"            
$regkey = $reg.OpenSubKey($key, $permchk, $regrights)            
$rs = $regkey.GetAccessControl()            
Write-Verbose "Create security principal"            
$user = New-Object -TypeName Security.Principal.NTaccount -ArgumentList "Administrators"            

Take a hive and key as parameters. Use a switch to set the Registry enumeration and then set the permissions and rights we want. Open the key and get the access controls.

Create a security principal for the Administrators group and set the group and owner in the access control. Use SetAccessControl to change the permissions

Recording and slides for July 2010 UG meeting

This months meeting covered working with the registry.

The slides and the demo script are available from


The recording is available

Richard Siddaway has invited you to view a Microsoft Office Live Meeting recording.
View Recording
Recording Details
    Subject: PowerShell and the Registry
    Recording URL:
    Recording ID: CB99JS
    Attendee Key: mm$2!",$G

Registry 7

One other aspect we need to cover is deleting individual values

$reg = [Microsoft.Win32.Registry]::LocalMachine
$key = $reg.OpenSubKey("Software\PSAM PSAdmins\Test", $true)

Open the key for writing and use the DeleteValue() method.

Registry 6

Having created some keys lets add some values

$reg = [Microsoft.Win32.Registry]::LocalMachine
$key = $reg.OpenSubKey("Software\ITKE PSAdmins", $true)
$key.SetValue("Dword Entry", 567 ,"Dword") 
$key.SetValue("String Entry", "My new string" ,"String") 
$key.SetValue("Expanded String Entry", "%COMPUTERNAME%" ,"ExpandString")

[string[]]$multi = "Z","Y","X"
$key.SetValue("Multi-string Entry", $multi ,"MultiString")

$key = $reg.OpenSubKey("Software\PSAM PSAdmins\Test", $true)
$key.SetValue("Oops", "Didn't mean to do this" ,"String")

This is very similar to the script we used to change the values – open the key for writing and use SetValue().  Just make sure we use the right data type.