2017-02-23 83 views
0

我在這裏做的是生成PRTG在運行腳本時可以解析的XML輸出。該腳本旨在確定最後一次安裝Windows Update的時間。它適用於所有遠程服務器,但當它在本地計算機上運行時,它不會獲得正確的$值。它最終是空的,而不是一個整數。我想我在這裏錯過了一些關於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

首先,你不應該爲您的本地系統做調用命令。您可以對結果進行驗證。

其次,對於本地調用,您需要將本地系統的IP /主機名添加到本地系統的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>" 

注:我沒有經歷過的每一步走了,我只是不停地裏的foreach循環驗證。希望能幫助到你。

+1

這沒有什麼錯遠程到本地系統的作爲概念。可能會出現這種情況,這並不合理,但沒有關於遠程訪問本地計算機的具體內容。還有一些情況很有意義。 – briantist

+0

@briantist:如果它在那裏,那麼你必須將本地系統添加到TrustedHosts列表中,並且我相信驗證應該有所幫助。 –

+1

這不一定是真的。遠程處理需要啓用,但域環境中不可信的主機。 – briantist

0

$value添加爲Invoke-Command cmdlet的ScriptBlock的最後一條語句。 $value的值應存儲在$result中。我認爲它與PowerShell遠程處理的序列化過程(也許它「自動序列化」分配的最後一個變量)有關。 「通常」,如果你想從PowerShell腳本塊返回一個值,你必須調用像「$ var」這樣的變量。因此$var的內容被髮送到管道中。有關詳細信息,請參閱此thread的答案。

作爲替代你也可以添加以下行到你的腳本:

return $value 

OR:

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

希望幫助

+0

你能解釋它爲什麼是自動序列化嗎?他正在爲所有的遠程系統獲取它,只有在本地它不是。可能是PS remoting在本地被禁用,或者本地系​​統未被添加到TrustedHosts列表中。 test-wsman應該在這種情況下提供幫助。請詳細說明你的觀點 –

+0

我很欣賞這些建議,但它們會打印出$值,而不是將$ value的內容傳遞給主腳本範圍。這會導致格式錯誤的XML輸出,其中內容不在XML標記中 也許我需要將寫主機「't $值」行移入Invoke-Command腳本塊。 –

+0

@Bollwerk:我已經更新了我的答案。你必須存儲'Invoke-Command'的輸出 - >我的帖子現在將輸出存儲在$ result中。檢查該值是否包含在'$ result'中。 – Moerwald