title: Powershell Remote Registry Access to Non-Domain Server
body: <p>I have the following script which I use to collect the installed applications on various servers:</p>
  
  <pre><code>$results = @()
  $list = Get-Content serverlist.txt
  foreach ($computer in $list) {
    echo "Processing $($computer)"
  
    if (Test-Connection -Cn $computer -BufferSize 16 -Count 1 -ea 0 -quiet ) {
      echo "Getting installed apps from $($computer) ..."
      $UninstallKey="SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall" 
      echo "Opening remote registry ..."
      $reg=[microsoft.win32.registrykey]::OpenRemoteBaseKey('LocalMachine',$computer) 
      echo "Getting registry keys ..."
      if ($reg) {
        $regkey=$reg.OpenSubKey($UninstallKey) 
        if ($regkey) {
          $subkeys=$regkey.GetSubKeyNames() 
          echo "Building result object ..."
          foreach($key in $subkeys){
              $thisKey=$UninstallKey+"\\"+$key 
              $thisSubKey=$reg.OpenSubKey($thisKey) 
              $obj = New-Object PSObject
              $obj | Add-Member -MemberType NoteProperty -Name "ComputerName" -Value $computer
              $obj | Add-Member -MemberType NoteProperty -Name "DisplayName" -Value $($thisSubKey.GetValue("DisplayName"))
              $obj | Add-Member -MemberType NoteProperty -Name "DisplayVersion" -Value $($thisSubKey.GetValue("DisplayVersion"))
              $obj | Add-Member -MemberType NoteProperty -Name "InstallLocation" -Value $($thisSubKey.GetValue("InstallLocation"))
              $obj | Add-Member -MemberType NoteProperty -Name "Publisher" -Value $($thisSubKey.GetValue("Publisher"))
              $results += $obj
          } 
        }
      }
    } else {
      echo "$($computer) is DOWN!"
      $obj = New-Object PSObject
      $obj | Add-Member -MemberType NoteProperty -Name "ComputerName" -Value $computer
      $obj | Add-Member -MemberType NoteProperty -Name "DisplayName" -Value "Down"
      $obj | Add-Member -MemberType NoteProperty -Name "DisplayVersion" -Value "Down"
      $obj | Add-Member -MemberType NoteProperty -Name "InstallLocation" -Value "Down"
      $obj | Add-Member -MemberType NoteProperty -Name "Publisher" -Value "Down"
      $results += $obj
    }
  }
  
  $results | Where-Object { $_.DisplayName } | select ComputerName, DisplayName, DisplayVersion, InstallLocation, Publisher | Export-Csv D:\Temp\InstalledApps.csv
  </code></pre>
  
  <p>This works fine on all of the domain member servers.  The issue comes when I try to get this to work on two non-domain Windows 2008R2 Standard servers.  One server works fine and the other server does not.  On the server that does not work, I get the following error:</p>
  
  <pre><code>Exception calling "OpenSubKey" with "1" argument(s): "Requested registry access is not allowed."
  </code></pre>
  
  <p>I cannot figure out why this would work for one server and not the other.  I am running the script from a non-elevated Powershell on a Windows 7 x64 machine.</p>
  
  <p>UPDATE:</p>
  
  <p>I used Process Monitor to track what the Remote Registry service was doing on both machines.  On the machine where things work OK, I see 4 reads of HKLM\System\CurrentControlSet\Control\SecurePipeServers\winreg and then it starts pulling the information I want from HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall.  On the machine where things are not working, Remote Registry does the same 4 reads of the winreg key but then it starts reading HKLM\System\CurrentControlSet\Control\SecurePipeServers\winreg\AllowedPaths and HKLM\System\CurrentControlSet\Control\SecurePipeServers\winreg\AllowedExactPaths.  I did some investigation and Remote Registry checks the permissions on the winreg key before proceeding.  I compared the good machine and bad machine and the registry keys and permissions are all exactly the same and are the default ones installed.</p>