2017-02-23 85 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

相关问题