【问题标题】:Get-WmiObject not functioning properly in foreach loopGet-WmiObject 在 foreach 循环中无法正常运行
【发布时间】:2017-08-22 20:37:19
【问题描述】:

我目前正在尝试编写一个脚本,该脚本获取加入我们域的计算机列表,一次遍历它们以检查它们是否存在于我创建的 Access DB 中,对它们运行 WMI 查询以收集它们的系统信息,并将该数据添加到数据库中(如果它们尚未在其中)。我可以在大多数计算机(大约一半)上成功执行此操作,但其中一些说找不到 RPC 服务器。

我知道其中一些错误是由于计算机处于脱机状态(防火墙已禁用且 WMI 查询已启用)。问题是一些计算机在线,当我在脚本中对它们运行Get-WmiObject 命令时,我得到了 RPC 服务器错误,但是当我在脚本之外单独运行命令时,我能够成功查询信息。我已经发布了导致奇怪行为的函数,并希望有更多编程知识的人能找到我犯的菜鸟错误。

第二个问题是,在第一次迭代之后,我得到下面的错误,说空白CompName 字段?前两次迭代按预期工作,然后它只是抛出一堆这些错误,“计算机之后已经存在”。

function Update-Systems {
    $PSCredential = Get-Credential
    $Comp = (Get-ADComputer -Filter * | select -ExpandProperty Name)

    foreach ($Computer in $Comp) {
        $RecordSet.MoveFirst()
        $RecordSet.Find("CompName = '$Computer'")
        $RecordCheck = $RecordSet.Fields.Item("CompName").Value

        if (!$RecordCheck) {
            "Collecting Data for $Record"
            $SystemProp = Get-WmiObject -Class Win32_ComputerSystem -Credential $PSCredential -ComputerName: $Computer -ErrorAction SilentlyContinue 
            $RecordSet.Addnew()
            $RecordSet.Fields.Item("DateRan") = Get-Date
            $RecordSet.Fields.Item("Domain") = $SystemProp.Domain
            $RecordSet.Fields.Item("CompName") = $SystemProp.Name
            $RecordSet.Fields.Item("Model") = $SystemProp.Model
            $RecordSet.Fields.Item("Manufacturer") = $SystemProp.Manufacturer
            $RecordSet.Update()
        } else {
            "Computer already exists"
        }
    }
}

【问题讨论】:

  • 请勿发布代码图片。
  • edit 您的问题以包含文本形式的代码。
  • @TrevorBrooks 对此感到抱歉,这是我第一次在 StackOverflow 上发帖。如果不能复制代码就没有多大用处.....
  • @lashing $RecordSet 是什么样的对象?
  • @Paolis $RecordSet = new-object -ComObject ADODB.Recordset`

标签: powershell recordset get-wmiobject


【解决方案1】:

Get-WmiObject 很可能无法从远程计算机查询信息。由于您指示 cmdlet 在发生错误时继续执行 (-ErrorAction SilentlyContinue),因此变量 $SystemProp 在发生错误时最终为空,因此 $SystemProp.Name 的计算结果也为 $null

您可以通过将$Computer 而不是$SystemProp.Name 分配给记录集来解决此问题,至少作为这样的后备:

$RecordSet.Fields.Item("CompName") = if (-not $SystemProp) {
    $Computer
} else {
    $SystemProp.Name
}

但是,更好的方法是进行适当的错误处理:

$ErrorActionPreference = 'Stop'
try {
    $SystemProp = Get-WmiObject -Class Win32_ComputerSystem -Credential $PSCredential -ComputerName $Computer
    $RecordSet.AddNew()
    $RecordSet.Fields.Item("DateRan")      = Get-Date
    $RecordSet.Fields.Item("Domain")       = $SystemProp.Domain
    $RecordSet.Fields.Item("CompName")     = $SystemProp.Name
    $RecordSet.Fields.Item("Model")        = $SystemProp.Model
    $RecordSet.Fields.Item("Manufacturer") = $SystemProp.Manufacturer
} catch {
    Write-Error $_ -ErrorAction Continue
}

你也可以retry几次然后放弃。

【讨论】:

  • 好的,经过一些测试后,我最终只是在执行Get-WmiObject 代码之前进行了一些检查。第一个检查 $RecordSet 是否有值。如果是这样,它将记录标记移动到数据库的开头,然后尝试查找计算机,如果记录检查返回 null,它将尝试查询数据并将其添加到数据库中。如果查询失败,它会说它无法查询信息。如果它确实获得了信息,它将把它添加到数据库中并启动下一台计算机。感谢大家的帮助!这消除了所有错误:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-02-13
  • 2015-05-16
  • 2023-03-28
  • 1970-01-01
  • 2016-06-05
  • 2013-06-17
  • 2015-03-14
相关资源
最近更新 更多