Get-WmiObject 在 foreach 循环中无法正常运行
Get-WmiObject not functioning properly in foreach loop
我目前正在尝试编写一个脚本,该脚本获取加入我们域的计算机列表,一次遍历它们以检查它们是否存在于我创建的 Access 数据库中,运行 WMI查询他们收集他们的系统信息,并将该数据添加到数据库中(如果它们尚未在其中)。我能够在大多数计算机(大约一半)上成功地这样做,但是其中一些计算机说找不到 RPC 服务器。
我知道其中一些错误是由于计算机处于脱机状态(禁用防火墙并启用 WMI 查询)造成的。问题是有些计算机在线,当我在脚本中对它们执行 运行 Get-WmiObject
命令时,我得到了 RPC 服务器错误,但是当我 运行 在外部单独执行命令时脚本的我能够成功查询信息。我已经发布了导致奇怪行为的函数,希望有更多编程知识的人能发现我犯的菜鸟错误。
第二个问题是,在第一次迭代后,我得到下面的错误,说空白 CompName
字段?前两次迭代按预期工作然后它只是用 "Computer already exists after".
抛出一堆这些错误
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"
}
}
}
很可能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
}
你也可以 几次才放弃。
我目前正在尝试编写一个脚本,该脚本获取加入我们域的计算机列表,一次遍历它们以检查它们是否存在于我创建的 Access 数据库中,运行 WMI查询他们收集他们的系统信息,并将该数据添加到数据库中(如果它们尚未在其中)。我能够在大多数计算机(大约一半)上成功地这样做,但是其中一些计算机说找不到 RPC 服务器。
我知道其中一些错误是由于计算机处于脱机状态(禁用防火墙并启用 WMI 查询)造成的。问题是有些计算机在线,当我在脚本中对它们执行 运行 Get-WmiObject
命令时,我得到了 RPC 服务器错误,但是当我 运行 在外部单独执行命令时脚本的我能够成功查询信息。我已经发布了导致奇怪行为的函数,希望有更多编程知识的人能发现我犯的菜鸟错误。
第二个问题是,在第一次迭代后,我得到下面的错误,说空白 CompName
字段?前两次迭代按预期工作然后它只是用 "Computer already exists after".
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"
}
}
}
很可能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
}
你也可以