2017-02-23 1 views
0

ここでは、スクリプトの実行時にPRTGが解析できるXML出力を生成しています。このスクリプトは、最新のWindows更新プログラムのインストールがいつ発生したかを判断することを目的としています。すべてのリモートサーバーでうまく動作しますが、ローカルマシン上で実行されている場合、正しい$値が得られません。整数ではなくヌルになります。私は、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-Commandコマンドを行うべきではありません。あなたは結果の検証をすることができます。

第2に、ローカルに呼び出す場合、意味のないローカルシステムのTrustedHostsリストにローカルシステムのIP /ホスト名を追加する必要があります。

私はニードフルを行う必要があり、あなたのコード内のWin32_ComputerSystemためWMIオブジェクトを使用して検証を続けています。

$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

$valueInvoke-CommandコマンドレットのScriptBlockの最後のステートメントとして追加します。 $valueの値は$resultに格納する必要があります。

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

が、私はそれがPowerShellリモート処理のシリアル化プロセスに関係していると思います(多分それは割り当てられた最後の変数を「自動シリアライズ」)。 "通常は" "$ var"のような変数を呼び出すPowerShellスクリプトブロックから値を返す場合。したがって、$varの内容がパイプラインで送信されます。詳細については、threadの回答を参照してください。

return $value 

OR:

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

希望

+0

自動直列化の理由を説明できますか?彼はすべてのリモートシステムのためにそれを手に入れています。ローカルでPSリモーティングが無効になっているか、ローカルシステムがTrustedHostsリストに追加されていない可能性があります。その場合、test-wsmanが役立つはずです。あなたのポイントを具体化してください –

+0

私は提案を感謝しますが、$ valueの内容をメインのスクリプトスコープに渡すのではなく、$値を出力します。その結果、XMLタグの内容がXMLタグに含まれない形式のXML形式が正しく生成されません。 Write-Hostの "t $ value"行をInvoke-Commandスクリプトブロックに移動する必要があります。 –

+0

@Bollwerk:答えを更新しました。あなたは 'Invoke-Command'の出力を保存しなければなりません - >私の投稿は出力を$ resultに保存します。値が '$ result'に含まれているかどうか確認してください。 – Moerwald

関連する問題