Home > other >  Go to next command if no result after 2 seconds
Go to next command if no result after 2 seconds

Time:01-11

I have large list of PC numbers (around 2000 -) I have a query with the following command:

$Computers = get-content = "C:\Users\Public\Documents\CSV\tfiles\Computernames.txt"

foreach ($Computer in $Computers) {
    query user /server:$Computer
}

I'm wondering if I can speed up this process by skipping the command if there is no result from a pc name after 2seconds..

Other, faster methods are also welcome.

CodePudding user response:

You can start a background job and wait for it only for 2 seconds:

$Computers = Get-Content "C:\Users\Public\Documents\CSV\tfiles\Computernames.txt"

foreach ($Computer in $Computers) {
    Start-Job { query user /server:$using:Computer } |Wait-Job -Timeout 2 |Receive-Job
}

If the job completes within 2 seconds, Receive-Job will unpack and output the query results. If the job doesn't complete within the timeout, then Receive-Job doesn't receive any input and the loop continues as normal.

For more information about PowerShell Jobs, see the about_Jobs help topic

CodePudding user response:

Re finding a faster method, let me complement Mathias R. Jessen's helpful answer with a PowerShell (Core) 7 solution that uses parallel execution via ForEach-Object -Parallel, combined with -AsJob:

$computers = Get-Content C:\Users\Public\Documents\CSV\tfiles\Computernames.txt

# Specify how many threads may run in parallel simultaneously,
# 5 by default. 
# For network-based operations, increasing that limit,
# via -ThrottleLimit, may make sense.
# For local operations, a limit that exceeds the number of CPU cores
# may decrease performance.
$maxParallelThreads = 10

# Start the parallel threads asynchronously and return them as a job.
$job = 
  $computers |
  ForEach-Object -AsJob -ThrottleLimit $maxParallelThreads -Parallel { 
    [pscustomobject] @{
      Computer = $_
      Result = query user /server:$_
    }
  }

# Receive job output in a polling loop, and terminate child jobs
# that have run too long.
do {
  Start-Sleep -Milliseconds 500 # Sleep a little; adjust as needed.
  # Get pending results.
  $job | Receive-Job
  # If any child jobs have been running for more than 2 seconds,
  # stop (terminate) them.
  # This will open up slots for more threads to spin up.
  foreach ($childJob in $job.ChildJobs.Where({ $_.State -eq 'Running' })) {
    if (([datetime]::now - $childJob.PSBeginTime).TotalSeconds -ge 2) {
      # Derive the target computer from the child job ID
      $targetComputer = $computers[$childJob.Id - $job.Id - 1]
      Write-Verbose -Verbose "Stopping job for computer '$targetComputer' due to running longer than 2 seconds..."
      $childJob | Stop-Job
    }
  }
} while ($job.ChildJobs.Where({ $_.State -in 'NotStarted', 'Running' }))

# Clean up.
$job | Remove-Job -Force
  • Related