0

It's my first post here, I'm tring to write scripts on PS on my own, now my target is to write script that checks if computer is online at network, for example: test-Connection 192.168.0.1, 2, 3 etc. Doing this one by one on loop for takes some time if some computers are offline, I've found some tutorials on this site to use -AsJob param, but I'm not really Sure how could it work. I mean I'd like to output every checked PC to excel, so i need if operator. eg:

if (Job1 completed successfull (computer pings)){ do smth}...

I need to get output from Job boolean (true/false), but one by one. I'm taking my first steps in PS, I've made program that checks it one by one in for loop, but as i said it take some time till my excel file fill...

I can see, that AsJob makes working more effective and I think it's important to understand it

Thanks and sorry for bad text formatting, by the time I'll go on with this!

Patryx
  • 11
  • 3
  • 2
    Does this answer your question? [If using Test-Connection on multiple computers with -Quiet how do I know which result is for which computer?](https://stackoverflow.com/questions/65998379/if-using-test-connection-on-multiple-computers-with-quiet-how-do-i-know-which-r). Note that `ForEach-Object -Parallel` creates jobs automatically behind the scenes. – zett42 Feb 20 '21 at 21:10
  • That's not really my problem, I'm trying to check multiple computers at one time, if I'd do it one by one, It'd take long while. I have problem with: How to output Recieve-Jobs like: $ip = (some IPs) $ip | Select-Object -Frist 3 | ForEach-Object{ Start-Job -Name $_ -ScriptBlock { $temp = Test-Connection $_ -Count 1 -Quiet if($temp){ Write-Host "$_ is online" } else{ write-host "$_ is offline" } } } I want to: When I Use Receive-Job output is: ip1 is online ip2 is offline ip3 is online (...) I want to check Ip's from 192.169.50.1 - 255 – Patryx Feb 20 '21 at 21:48
  • With `ForEach-Object -Parallel` you actually check multiple computers at the same time. It is like creating jobs, but much simpler to handle. By default, it creates 5 jobs at maximum. You can increase that like `ForEach-Object -Parallel -ThrottleLimit 10`. Now it would run 10 jobs at maximum. – zett42 Feb 20 '21 at 22:02
  • Just a note that `ForEach-Object -Parallel` is not available until Powershell v7. – Daniel Feb 20 '21 at 22:12
  • I've replied an error: ForEach-Object : Parameter set cannot be resolved using the specified named parameters.I think It's no longer avalible "param -Parallel" Anybody has any tips? I'd Like just to get output if job was completed successfull or not, than I could use if statment to simply fill excel cells with IP and status – Patryx Feb 20 '21 at 22:22
  • https://wtools.io/paste-code/b3MP I'm trying to run this, but It won't output anything... – Patryx Feb 20 '21 at 22:32

1 Answers1

1

In your example, in the Start-Job scriptblock you are trying to access $_ which is not available in the codeblock scope. If you replace $_ with $args[0] it should work since you are passing in the $ip value as an argument

Your Example

$ipki = Get-Content 'C:\Users\pchor\Desktop\ipki.txt'
foreach ($ip in $ipki) {
    Start-Job -Name "$ip" -ScriptBlock {
        Test-Connection $_ -Count 1  # <---- replace $_ with $args[0]
    } -ArgumentList $_  # <----- change $_ to $ip 
}

You'll probably also want to wait for all the jobs to finish. I recommend something like this

$computers = @(
    'www.google.com'
    'www.yahoo.com'
)

$jobs = $computers |
    ForEach-Object {
        Start-Job -ScriptBlock {
            [pscustomobject]@{
                Computer = $using:_
                Alive    = Test-Connection $using:_ -Count 1 -Quiet
            }
        }
    }

# Loop until all jobs have stopped running
While ($jobs |
        Where-Object { $_.state -eq 'Running' }) {
    "# of jobs still running $( ($jobs | Where-Object {$_.state -eq 'Running'}).Count )";
    Start-Sleep -Seconds 2
}
$results = $jobs | Receive-Job | Select-Object Computer, Alive
$results | Format-Table

Output

Computer       Alive
--------       -----
www.google.com  True
www.yahoo.com   True

To modify the properties to what you want there are different ways of doing this. Easiest in this case is probably to use a calculated property

$newResults = $results | 
    Select-Object Computer, 
    @{Label = 'State'; Expression = { if ($_.Alive) { 'Online' } else { 'Offline' } } }

Objects will now look like this (I added another fake address to illustrate offline state)

Computer                 State
--------                 -----
www.google.com           Online
www.yahoo.com            Online
xxx.NotAValidAddress.xxx Offline

You can then export the objects to csv using Export-csv

$newResults | Export-Csv -Path c:\temp\output.csv
Daniel
  • 4,792
  • 2
  • 7
  • 20
  • Yes, that's what I wanted, how could I access "true" value of every single adress? for example: If (www.google.com -eq True){ write-host= "Online" } else{ Write-host = "offline" } – Patryx Feb 20 '21 at 23:37
  • Updated answer to include how to transform the object with calculated property and how to export the data to csv file – Daniel Feb 20 '21 at 23:55
  • Perfect! Thank you very much, now It's time to analyse your code to understand it! B) – Patryx Feb 22 '21 at 17:06