简体   繁体   中英

Powershell: Pipe variable $_ in if statement?

I have the following short script to grab serial numbers of computers and monitors in an OU, which works fine:

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 ""};

This script doesn't check to see if the computer is online before attempting to fetch the WMIObject, so if a computer is offline it takes ages before the RPC call times out.

I tried to modify the script to use the Test-Connection cmdlet before trying to get the WMIObject:

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";
}

I'm sure I'm doing something syntactically stupid. Can someone point me in the right direction?

You can't pipe directly to an if statement, only to cmdlets.

Put the if statement inside the ForEach-Object block ( % is an alias for ForEach-Object ):

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

If you don't care about writing each machine's status to the host, you could also filter out offline computers with Where-Object (alias ? ):

... | Select-Object -Expand Name | ?{ 
  Test-Connection $_ -Quiet 
} | % {
  Get-WmiObject -ComputerName $_
} 

In addition to the answer from @Mathias R. Jessen, you can get rid of the backticks for line continuation.

They are not needed if the end of the line infers there is another block of code required for the statement. Like | or { or ( .

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

works just fine...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM