У меня есть следующий скрипт, который я использую для сбора установленных приложений на различных серверах:
$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
Это отлично работает на всех членских серверах домена. Проблема возникает, когда я пытаюсь заставить это работать на двух серверах Windows 2008R2 Standard, не относящихся к домену. Один сервер работает нормально, а другой нет. На сервере, который не работает, я получаю следующую ошибку:
Exception calling "OpenSubKey" with "1" argument(s): "Requested registry access is not allowed."
Я не могу понять, почему это сработает для одного сервера, а не для другого. Я запускаю сценарий из Powershell без повышенных прав на машине с Windows 7 x64.
ОБНОВИТЬ:
Я использовал Process Monitor, чтобы отслеживать, что делает служба удаленного реестра на обеих машинах. На машине, где все работает нормально, я вижу 4 чтения HKLM \ System \ CurrentControlSet \ Control \ SecurePipeServers \ winreg, а затем он начинает извлекать нужную мне информацию из HKLM \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Uninstall. На машине, где что-то не работает, удаленный реестр выполняет те же 4 чтения ключа winreg, но затем начинает читать HKLM \ System \ CurrentControlSet \ Control \ SecurePipeServers \ winreg \ AllowedPaths и HKLM \ System \ CurrentControlSet \ Control \ SecurePipeServers \ winreg \ AllowedExactPaths. Я провел небольшое расследование, и Remote Registry проверил разрешения для ключа winreg, прежде чем продолжить. Я сравнил хорошую машину и плохую, и все ключи реестра и разрешения абсолютно одинаковы и установлены по умолчанию.