Powershell:if 语句中的管道变量 $_?

Powershell: Pipe variable $_ in if statement?

我有以下简短的脚本来获取 OU 中计算机和显示器的序列号,效果很好:

Import-Module ActiveDirectory

$searchbase = "OU=some,OU=organisational,OU=units,DC=somedomain,DC=local"

Write-Host ""
Write-Host "Serial Numbers for Computers and Monitors in" $searchbase
Write-Host "--"
Get-ADComputer -SearchBase $searchbase -Filter '*' | `
Select-Object -Expand Name | %{Write-Host ""; echo $_ ; Get-WMIObject -Class Win32_BIOS -ComputerName $_ | Select-Object -Expand SerialNumber; `
$monitor = gwmi WmiMonitorID -Namespace root\wmi -computername $_; ($monitor.SerialNumberID | foreach {[char]$_}) -join ""};

此脚本在尝试获取 WMIObject 之前不会检查计算机是否在线,因此如果计算机处于离线状态,则 RPC 调用超时之前需要很长时间。

在尝试获取 WMIObject 之前,我尝试修改脚本以使用 Test-Connection cmdlet:

Import-Module ActiveDirectory

$searchbase = "OU=some,OU=organisational,OU=units,DC=somedomain,DC=local"

Write-Host ""
Write-Host "Serial Numbers for Computers and Monitors in" $searchbase
Write-Host "--"
Get-ADComputer -SearchBase $searchbase -Filter '*' | `
Select-Object -Expand Name | `
if (Test-Connection -ComputerName $_ -Quiet) {
%{Write-Host ""; echo $_ ; Get-WMIObject -Class Win32_BIOS -ComputerName $_ | Select-Object -Expand SerialNumber; `
$monitor = gwmi WmiMonitorID -Namespace root\wmi -computername $_; ($monitor.SerialNumberID | foreach {[char]$_}) -join ""};}
}
else {
Write-Host ""; Write-Host $_ "is offline";
}

我确定我在做一些语法上愚蠢的事情。有人能指出我正确的方向吗?

您不能直接传送到 if 语句,只能传送到 cmdlet。

if 语句 放在 ForEach-Object 中(%ForEach-Object 的别名):

... | Select-Object -Expand Name | `
  %{
    if (Test-Connection -ComputerName $_ -Quiet) {
      # Get-WmiObject in here
    }
    else {
      Write-Host ""; Write-Host $_ "is offline";
    }
  }

如果您不关心将每台机器的状态写入主机,您还可以通过 Where-Object(alias ?):

过滤掉离线计算机
... | Select-Object -Expand Name | ?{ 
  Test-Connection $_ -Quiet 
} | % {
  Get-WmiObject -ComputerName $_
} 

除了@Mathias R. Jessen 的回答之外,您还可以去掉续行的反引号。

如果行尾推断语句需要另一个代码块,则不需要它们。喜欢 |{(.

"foo", "bar" |
% {$_}

工作正常...