I need help because I'm having trouble using my variables in powershell jobs.
Let me explain
I want to create a counter to retrieve the number of ping OK
foreach($computer in $computers)
{
Start-ThreadJob -ThrottleLimit 100 -ScriptBlock {
if (Test-Connection $using:computer -count 1 -TimeoutSeconds 2 -Quiet)
{
$test_con = $test_con+1
}
}
}
write-host $test-con
I have no problem getting the $computer variable in start threadjob using the $using scope. But I can't increment the test_con variable each time test-connection is true, to get at the end the number of machines that ping.
I want to increment my global variable 'test_con' from jobs
I am using powershell 7, I never asked myself the question under bash linux
Could someone kindly explain to me how it works with powershell ?
You can indeed use the using
scope modifier to resolve variable references in the calling scope, you just need a variable with a thread-safe collection type to write to:
# Create a hashtable
$counterTable = @{}
# Make it thread-safe
$counterTable = [hashtable]::Synchronized($counterTable)
foreach($computer in $computers) {
Start-ThreadJob -ThrottleLimit 100 -ScriptBlock {
if (Test-Connection $using:computer -count 1 -TimeoutSeconds 2 -Quiet)
{
$counter = $using:counterTable
$counter['ping'] += 1
}
}
}
Write-Host "We had $($counterTable['ping']) successful pings!"
I'd personally prefer knowing which computers we could ping successfully, so I'd suggest storing the Test-Connection
results in separate entries in the table instead:
# Create a hashtable
$pingTable = @{}
# Make it thread-safe
$pingTable = [hashtable]::Synchronized($pingTable)
foreach($computer in $computers) {
Start-ThreadJob -ThrottleLimit 100 -ScriptBlock {
$pingTable = $using:pingTable
$computerName = $using:computer
$pingTable[$computerName] = Test-Connection $using:computer -Count 1 -TimeoutSeconds 2 -Quiet
}
}
Write-Host "We had $($pingTable.psbase.Values.Where({!$_}).Count) failures!"
$pingTable.GetEnumerator() |Sort Name |Format-Table |Out-Host