0
votes

I'm trying to create a simple network scanner using PowerShell and I want it to run multiple "pings (or in this case test-connection)" in parallel.

Start-Job seems to be the best way to accomplish this multi-threading scenario.

Here is a simplified example of what i'm trying to do.

$list=@("192.168.1.1", "192.168.1.2", "192.168.1.3", "192.168.1.4")

ForEach ($item In $list) {
  Start-Job -ScriptBlock {
    if (Test-Connection $item -Quiet -Count 1) {
      Add-Content -value "$item found" -Path C:\logs\test.txt
    }
  }
}

This however does nothing. If I remove the Start-Job part it does work, but loses its multiprocessing. If I remove the if statement the writing to file part works.

So the issue seems to be when using an if statement in a scriptblock within a job.

There must be something about the start-job command i'm missing. Or is there any better way to create this kind of script?

1
Well, the first issue that I see is the potential for file lock collisions on the file you are trying to write to. - EBGreen
I created a script with a for loop (1-1000) that creates jobs that writes to the file and it works. so don't think that is the issue. - Jack Pettersson
I'm not saying that it is the issue. I'm saying that this is a bad way to write your code. It is not thread safe. Doing it with a 1-1000 loop is not the same situation at all and is thread safe. - EBGreen
Well, the 1-1000 if not guarantedd to be thread safe either but it is much much less likely to generate collisions. - EBGreen
The issue with the Start-Job is scope. You need to pass the IP into the scriptblock - EBGreen

1 Answers

0
votes

$item is not available within the scriptblock scope, so you need to pass the value in as an argument.

$list=@("192.168.1.1", "192.168.1.2", "192.168.1.3", "192.168.1.4")

ForEach ($item In $list) {
  Start-Job -ScriptBlock {
    param($item)
    if (Test-Connection $item -Quiet -Count 1) {
      Add-Content -value "$item found" -Path C:\logs\test.txt
    }
  } -argumentlist $item
}