I've got this running but I changed the PortOpen because if systems were down, this block would take too long to run. However, after I made the change, I thought I was good until I had come to test it again and again and somehow, I have different results for systems. Sometimes the same system comes up twice without the other. And sometimes doubles of both. I had hoped I can set the timeout faster this way. The PortOpen line does work, but I'm not sure how to get it to work as a whole within this job. Basically, I'm not sure how to structure this to be able to leverage that piece.
$ProgressPreference = 'Ignore'
$maxThreads = 32
$pool = [runspacefactory]::CreateRunspacePool(1, $maxThreads,
[initialsessionstate]::CreateDefault2(),
$Host)
$pool.Open()
$jobs = [System.Collections.Generic.List[hashtable]]::new()
$servers = ( Get-ADComputer -filter * -searchbase "OU=Sales, DC=example,DC=com" | Select-Object -expand Name )
$servers | ForEach-Object {
$instance = [powershell]::Create().AddScript({
param($computer)
[pscustomobject]@{
Computer = $computer
Port = 5985
#PortOpen = Test-NetConnection $computer -Port 5985 -InformationLevel Quiet
PortOpen = [System.Net.Sockets.TcpClient]::new().ConnectAsync($computer, 5985).Wait(100)
}
}).AddParameters(@{ computer = $_ })
$instance.RunspacePool = $pool
$jobs.Add(@{
Instance = $instance
Async = $instance.BeginInvoke()
})
}
$result = while($jobs) {
$job = $jobs[[System.Threading.WaitHandle]::WaitAny($jobs.Async.AsyncWaitHandle)]
$job.Instance.EndInvoke($job.Async)
$job.Instance.Dispose()
$null = $jobs.Remove($job)
}
$pool.Dispose()
$online = @()
$online += $result | Where-Object PortOpen | ForEach-Object Computer
Write-Output $online
As I've stated in comments, I don't really see something wrong with your code that could be causing output being duplicated or missing output. I do see though that 100ms to await the task is too little time, I would recommend at least 1 second.
Another point is that
WaitHandle.WaitAnysupports top 63 wait handles in STA Mode (PowerShell default), from the Remarks section of the documentation:Ideally, you would need to consume the tasks if that number is reached in the first loop before continuing with the rest (this requires additional logic that checks if
$jobs.Count -eq 63).Lastly, I would recommend error handling in your code, this is to avoid aggregate exceptions caused by the
.Waitmethod.Now, since you're already aware of and currently have installed the
PSParallelPipelineModule, this is how I would approach the code: