# Test for connection before running Invoke-command

**URL:** <https://forums.powershell.org/t/test-for-connection-before-running-invoke-command/1171>\
**Category:** PowerShell Help\
**Created:** [December 31, 2011, 6:30pm UTC](https://forums.powershell.org/t/test-for-connection-before-running-invoke-command/1171 "2011-12-31T18:30:00Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![archives](https://avatars.discourse-cdn.com/v4/letter/a/bb73d2/32.png) [@archives](https://forums.powershell.org/u/archives)\
**Post date:** [December 31, 2011, 6:30pm UTC](https://forums.powershell.org/t/test-for-connection-before-running-invoke-command/1171/1 "2011-12-31T18:30:00Z")

</div>

by hammer5 at 2013-03-20 14:14:42

> Hello I was wondering if anyone had an example of how to test if a group of computers are available before running the Invoke-command cmdlet?  
> Here is an example command  
> `Invoke-Command -ComputerName $computer -ScriptBlock{Get-itemProperty ‘HKLM:\SYSTEM\CurrentControlSet\Control\Class{4D36E965-E325-11CE-BFC1-08002BE10318}’}`  
> I would like to test that each computer in $computer is available before the command is ran, or at least catch the error and report that the computer is offline.  
>   
> I have tried this   
> `$computers = Get-Content C:\scripts\computers1.txt$computerstatus = @()foreach ($computer in $computers) {if(Test-Connection $computer -count 1 -Quiet){ #Invoke-Command -ComputerName $Computer {$env:COMPUTERNAME +" - "+(Test-Path ‘c:\program files (x86)\Microsoft Office\office14\winword.exe’)} #$CheckReg = Invoke-Command -ComputerName $computer -ScriptBlock{Get-itemProperty ‘HKLM:\SYSTEM\CurrentControlSet\Control\Class{4D36E965-E325-11CE-BFC1-08002BE10318}’} $objStatus = New-Object System.Object $objStatus | Add-Member -type NoteProperty -name ComputerName -value $computer $objStatus | Add-Member -type NoteProperty -name Status -Value "Online" #$objStatus | Add-Member -type NoteProperty -name Lowerfilters -Value $CheckReg.Lowerfilters #$objstatus | Add-Member -type NoteProperty -name Upperfilters -Value $CheckReg.Upperfilters $computerstatus += $objStatus }#Close if test-connection else { $objStatus = New-Object System.Object $objStatus | Add-Member -type NoteProperty -name ComputerName -value $computer $objStatus | Add-Member -type NoteProperty -name Status -Value "Offline" $computerstatus += $objStatus } #Close Else } #Close Foreach# build list of computers to check$computerstocheck = $computerstatus | where {$_.Status -eq "Online"} | Select -ExpandProperty computername | out-string$CheckReg = Invoke-Command -ComputerName $computerstocheck -ScriptBlock{Get-itemProperty ‘HKLM:\SYSTEM\CurrentControlSet\Control\Class{4D36E965-E325-11CE-BFC1-08002BE10318}’}`  
> When I run the script it states One or more computer names is not valid. and I do not think I’m going about it correctly any way. My thought was that I would build a custom object to hold the status and the run the invoke-command against that list, but It’s not working very good.  
> Any idea’s will be greatly appreciated.

by DonJ at 2013-03-20 15:39:25

> Welcome! Consider using the CODE button to format your script - makes it a ton easier to read.  
>   
> You can do a couple of things. You could ping the machine using Test-Host… but that doesn’t tell you if Remoting will work. It’s just a ping. There’s also a Test-WSMan\* cmdlet that actually "pings" the WinRM service on the remote machine. That’s probably best. Or, just trap the error from Invoke-Command - which is the fastest, since if it works you won’t have wasted time pinging.   
>   
> What approach do you like?  
>   
> It’d also help to see your input file with the computer names.

by hammer5 at 2013-03-20 17:27:08

> Sorry for not using the code option. I would like to be able to trap the errors. As for the input file its just a text file with computer names one on each line. As you might notice I tried to use test-connection in an if statement, but you are correct it was real slow. The output I’m looking for would be a list of computer with the read registry keys. Ideally in a object.  
>   
> V/r  
> John

by DonJ at 2013-03-21 06:46:10

> Ok, trapping is probably easier than all that checking you’re doing.  
>   
> `Try { Invoke-Command -ErrorAction Stop (add the rest of your parameters here)} Catch { # this will run if an error occurs}`  
>   
> That’s the basic form. Rather than creating some internal status object, I’d suggest just enumerating your computers and making a new array of ones you CAN reach. For example:  
>   
> `$newcomputers = @()foreach ($computer in $computers) { Try { $reachable = $true Invoke-Command -ErrorAction Stop -ComputerName $computer -scriptblock { #whatever } } Catch { # this will run if an error occurs $reachable = $false } if ($reachable) { $newcomputers += $computer }}`  
>   
> Then you’ll know what computers ($newcomputers) worked. Note that this technique is going to Invoke-Command in sequential order, rather than in parallel. If the command you’re running is BIG, and you want them in parallel, then in the Invoke-Command I suggest, just do something short (like run Get-Service). Then after the ForEach loop you can Invoke-Command your REAL command against $newcomputers. In other words, I’m using Invoke-Command as a kind of "ping," since it’s testing the full service and not just ICMP connectivity. Not the only approach you could take - but I don’t think you need to build a big status object in your code; just build a list of comuters that worked.

by hammer5 at 2013-03-21 13:35:55

> Thanks Mr. Jones, That really helped.  
> Here is what I have so far:  
> `$computers = Get-Content C:\script\testing.txt$Onlinecomputer = @()$RegResult = @()Foreach ($computer in $computers) { Try { $reachable = $true $Result = Invoke-Command -ErrorAction Stop -computername $computer -scriptblock { Get-itemProperty ‘HKLM:\SYSTEM\CurrentControlSet\Control\Class{4D36E965-E325-11CE-BFC1-08002BE10318}’ } #Close Results } Catch { #This will run if an error occurs $reachable = $false } #close catch If ($reachable) { $Onlinecomputer += $computer $RegResult += $Result }# Clost reachable if If (!$reachable){ $Result = "" | Select PSComputerName, Status $Result.Status = "Not Online" $Result.pscomputername = $computer $RegResult += $result } #Close notreachable if } $RegResult | select pscomputerName, LowerFilters, UpperFilters, Status | Format-Table * `  
> I did have another question? It’s a little off topic, but pretty simple in the first line [quote]$Computer = Get-content C:\script\testing.txt [/quote]  
> If I wanted to replace the Get-content command with my own list for testing purposes how would I do that? I tried `$computers = "localhost, NotOnline"` but as you know that failed. How could I get a shorter list of computers into the $computers variable without creating a short txt file?  
>   
> Thank you very much for your help and willingness share your knowledge!

by DexterPOSH at 2013-03-27 16:49:26

> [quote="hammer5"]If I wanted to replace the Get-content command with my own list for testing purposes how would I do that? I tried  
> CODE: SELECT ALL  
> $computers = "localhost, NotOnline"  
> but as you know that failed. How could I get a shorter list of computers into the $computers variable without creating a short txt file?[/quote]  
>   
> You will have to use the following  
> `$computers = "localhost","NotOnline"`  
> Why ? If you use **$computers = "localhost, NotOnline"** then it is a string not a collection, this would be evident if you do this in the console:  
> `$computers = "localhost, NotOnline"$computers.GetType().fullname`  
> and later do this`$computers = "localhost","NotOnline"$computers.GetType().fullname`  
> P.S. - learned the neat trick to use try {} catch{} with Invoke-Command to test for connection 🙂  
> Hope this helps

---

<div class="post-metadata">

**Author:** ![dotnVo](https://avatars.discourse-cdn.com/v4/letter/d/4af34b/32.png) [@dotnVo](https://forums.powershell.org/u/dotnVo)\
**Post date:** [May 16, 2024, 8:58pm UTC](https://forums.powershell.org/t/test-for-connection-before-running-invoke-command/1171/2 "2024-05-16T20:58:08Z")

</div>

Closed on May 16, 2024, 8:58pm UTC


