Home > Net >  PowerShell script that makes multiple other PowerShell windows, and makes them all run one command s
PowerShell script that makes multiple other PowerShell windows, and makes them all run one command s

Time:07-14

I have:

for($i = 1 ; $i -le 3; $i  )
    {
        Start-Process powershell.exe
    }

but I don't know how I would make the new windows run a ping command. Could be done with an extra script but have no idea. Thanks

CodePudding user response:

Start-Process has an -ArgumentList parameter that can be used to pass arguments to the new PowerShell process.

powershell.exe and pwsh.exe have a -Command parameter that can be used to pass them a command.

You can combine the two like this:

for ($i = 1; $i -le 3; $i  ) 
{ 
    Start-Process powershell.exe -ArgumentList '-NoExit',"-Command ping 127.0.0.$i" 
}

If you don't use the -NoExit parameter the window will close as soon as the ping command finishes.

As mentioned in the comments to the question it is also possible to ping multiple hosts using the Test-Connection command like this:

Test-Connection -TargetName 127.0.0.1,127.0.0.2

This has a downside though in that it seems to ping one after the other rather than doing it in parallel.

Another way to do much the same thing in parallel, and probably more PowerShell style is to use jobs:

$jobs = @()
for ($i = 1; $i -le 3; $i  )
{
    $jobs  = Start-ThreadJob -ArgumentList $i { PARAM ($i)
        Test-Connection "127.0.0.$i"
    }
}
Wait-Job $jobs
Receive-Job $jobs -Wait -AutoRemoveJob

Note: Start-ThreadJob is newish. If you're still stuck on version 5 of PowerShell that comes with Windows use Start-Job instead, it spawns new processes where as Start-ThreadJob doesn't.

Nitpickers' corner

For those in the comments saying that appending to an array is slow. Strictly a more PowerShell way of doing this is given below. For three items, however, you won't be able to measure the difference and the readability of the code is way lower. It's also rather diverging from the original question.

1..3 | % { Start-ThreadJob -ArgumentList $_ { PARAM($i) Test-Connection "127.0.0.$i" } } | Wait-Job | Receive-Job -Wait -AutoRemoveJob

CodePudding user response:

Here's a pinger script I have to watch multiple computers.

# pinger.ps1

# example:  pinger comp001
# pinger $list

param ($hostnames)

#$pingcmd = 'test-netconnection -port 515'
$pingcmd = 'test-connection'

$sleeptime = 1

$sawup = @{}
$sawdown = @{}

foreach ($hostname in $hostnames) { 
  $sawup[$hostname] = $false
  $sawdown[$hostname] = $false
}

#$sawup = 0
#$sawdown = 0

while ($true) {
  # if (invoke-expression "$pingcmd $($hostname)") {

  foreach ($hostname in $hostnames) {
    if (& $pingcmd -count 1 $hostname -ea 0) {
      if (! $sawup[$hostname]) {
        echo "$([console]::beep(500,300))$hostname is up $(get-date)"
#        [pscustomobject]@{Hostname = $hostname; Status = 'up'; Date = get-date} # format-table waits for 2 objects
        $sawup[$hostname] = $true
        $sawdown[$hostname] = $false
      }
    } else {
      if (! $sawdown[$hostname]) {
        echo "$([console]::beep(500,300))$hostname is down $(get-date)"
#        [pscustomobject]@{Hostname = $hostname; Status = 'down'; Date = get-date}
        $sawdown[$hostname] = $true
        $sawup[$hostname] = $false
      }
    }
  }
  
  sleep $sleeptime
}

Example usage (it beeps):

.\pinger comp001,comp002

comp001 is up 07/13/2022 12:07:59
comp002 is up 07/13/2022 12:08:00
  • Related