stoo
stoo

Reputation: 97

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?

Upvotes: 0

Views: 4162

Answers (2)

Mathias R. Jessen
Mathias R. Jessen

Reputation: 174690

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 $_
} 

Upvotes: 6

Kory Gill
Kory Gill

Reputation: 7163

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...

Upvotes: 2

Related Questions