2017-02-23 56 views
0

Что я делаю здесь, это генерация вывода XML, которое PRTG может анализировать при запуске скрипта. Сценарий предназначен для определения того, когда произошла последняя установка обновления Windows. Он отлично работает для всех удаленных серверов, но когда он запускается на локальном компьютере, он не получает правильное значение $. Он заканчивается как null, а не целое число. Я предполагаю, что у меня что-то отсутствует в том, как Invoke-Command работает на локальном сервере и удаленном сервере. Кто-нибудь возражал бы, показывая мне, где я совершил ошибку?Блок сценария Invoke-Command возвращает переменную с удаленных серверов, но не с локального сервера

$ErrorActionPreference = "Stop" 
#Get a list of servers 
$servers = Get-ADComputer -SearchBase 'DC=<removed>,DC=int' -Filter {OperatingSystem -NotLike "Windows Server 2003*"} | Sort Name | Select -ExpandProperty Name 
$value = "" 
#This is the start of the XML output that PRTG will be parsing when the code runs 
Write-Host "<prtg>" 
#Loop through all servers and attempt to get a value for last windows update install. 
foreach($server in $servers) { 
    Write-Host "`t<result>`n`t<channel> $server </channel>" 
    try { 
     Invoke-Command -ComputerName $server -ScriptBlock { 
      $props = @{ 
       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 
       } 
      $stringdato = $props.LastInstall; 
      $DATO = ([datetime]::ParseExact($stringdato, "yyyy-MM-dd HH:mm:ss", $null)) 
      $today = (Get-Date) 
      $timeout = ($today - $DATO) 
      $value = $timeout.Days 
     } 
    } catch { 
     # set value to 999 if there is a problem, for PRTG's error threshold. 
     $value = 999 
    } 
    Write-Host "`t<value>$value</value>" 
    Write-Host "`t<CustomUnit>days</CustomUnit>`n`t<LimitMaxError>90</LimitMaxError>`n`t<LimitMaxWarning>60</LimitMaxWarning>`n`t<LimitMode>1</LimitMode>`n`t</result>`n" 
} 
Write-Host "</prtg>" 

ответ

0

Прежде всего, вы не должны делать Invoke-команды для вашей локальной системы. Вы можете поместить эту проверку для результирующего.

Во-вторых, для локального вызова вам необходимо добавить IP/hostname локальной системы в список TrustedHosts для локальной системы, что не имеет смысла.

я держал проверку с помощью Wmi-объект для Win32_ComputerSystem в вашем коде, который должен сделать необходимое.

$ErrorActionPreference = "Stop" 
#Get a list of servers 
$servers = Get-ADComputer -SearchBase 'DC=<removed>,DC=int' -Filter {OperatingSystem -NotLike "Windows Server 2003*"} | Sort Name | Select -ExpandProperty Name 
$value = "" 
#This is the start of the XML output that PRTG will be parsing when the code runs 
Write-Host "<prtg>" 




#Loop through all servers and attempt to get a value for last windows update install. 
foreach($server in $servers) { 
    Write-Host "`t<result>`n`t<channel> $server </channel>" 
    try { 

    $LocalNetwork=Get-WmiObject Win32_Computersystem; 

    ## IF its a local system, then it will go inside IF 
    if($LocalNetwork.Name -eq ($server.trim())) 
       { 


      $props = @{ 
       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 
       } 
      $stringdato = $props.LastInstall; 
      $DATO = ([datetime]::ParseExact($stringdato, "yyyy-MM-dd HH:mm:ss", $null)) 
      $today = (Get-Date) 
      $timeout = ($today - $DATO) 
      $value = $timeout.Days 



       } 
    ## If its a remote system, it will go inside else and will do invoke 
     else { 
     Invoke-Command -ComputerName $server -ScriptBlock { 
      $props = @{ 
       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 
       } 
      $stringdato = $props.LastInstall; 
      $DATO = ([datetime]::ParseExact($stringdato, "yyyy-MM-dd HH:mm:ss", $null)) 
      $today = (Get-Date) 
      $timeout = ($today - $DATO) 
      $value = $timeout.Days 
     } 
     } 
    } 

    catch { 
     # set value to 999 if there is a problem, for PRTG's error threshold. 
     $value = 999 
    } 
    Write-Host "`t<value>$value</value>" 
    Write-Host "`t<CustomUnit>days</CustomUnit>`n`t<LimitMaxError>90</LimitMaxError>`n`t<LimitMaxWarning>60</LimitMaxWarning>`n`t<LimitMode>1</LimitMode>`n`t</result>`n" 

} 
Write-Host "</prtg>" 

Примечание: Я не прошел через каждый шаг, я просто продолжал проверку внутри Еогеаспа цикла. Надеюсь, поможет.

+1

Там нет ничего плохого с удаленным доступом в локальную систему как концепция. Могут быть ситуации, когда это не имеет смысла, но нет ничего особенного в удалении на локальную машину, что плохо. Есть также ситуации, когда это имеет большой смысл. – briantist

+0

@briantist: если он есть, вам нужно добавить локальную систему в список TrustedHosts, а также я считаю, что проверка должна помочь. –

+1

Это не обязательно так. Необходимо удалить удаленные, но не доверенные хосты в среде домена. – briantist

0

Добавить $value как последний оператор ScriptBlock команды Invoke-Command. Значение $value должно храниться в $result.

... 
$result = Invoke-Command -ComputerName $server -ScriptBlock { 
     ... 
     $timeout = ($today - $DATO) 
     $value = $timeout.Days 
     $value # <---- ADD THIS LINE 
     ... 

Я думаю, что он должен делать с процессом сериализации PowerShell Remoting (может быть, это «автоматически упорядочивает» последнюю переменную, которая была назначена). «Обычно», если вы хотите вернуть значение из скриптового блока PowerShell, вы должны вызвать переменную типа «$ var». Поэтому содержимое $var отправляется по трубопроводу. См. Ответ на этот вопрос thread.

В качестве альтернативы вы можете также добавить следующие строки в ваш скрипт:

return $value 

ИЛИ:

$value # <----- sent the content of $value down the pipeline 
return 

Надежда, что помогает

+0

Можете ли вы объяснить, почему это автоматическая сериализация? Он получает его для всех удаленных систем, и только для локальных это не так. Может быть, удаленный доступ к PS отключен в локальной сети или может быть локальная система не добавляется в список TrustedHosts. test-wsman должен помочь в этом случае. Пожалуйста, уточните свою точку зрения –

+0

Я ценю предложения, но они печатают значение $, а не передают содержимое значения $ в область основного сценария. Это приводит к ошибочному выводу XML, где содержимое не находится внутри тега XML. Возможно, мне нужно переместить строку Write-Host «' t $ value »в блок сценария Invoke-Command. –

+0

@Bollwerk: Я обновил свой ответ. Вы должны сохранить вывод 'Invoke-Command' -> my post теперь сохранить результат в $ result. Проверьте, включено ли значение в '$ result'. – Moerwald