У меня этот код хорошо работает синхронно с powershell.Invoke(), однако с powershell.BeginInvoke() я не могу зафиксировать вывод. Чтобы использовать приведенный ниже код, вам нужно заполнить переменную $servers, иначе она должна работать.
Я попытался зафиксировать вывод, добавив каждый поток в переменную $threads при использовании EndInvoke(), и я могу видеть дескриптор потока и значение iscompleted, однако я не могу понять, где значение, которое я возвращаю с возвратом сохраняется часть каждой функции.
Первый блок - это вывод, который я вижу, показывая false для одного асинхронного завершения, пока он не завершится, а затем все дескрипторы потоков показывают true.
Спасибо!
8804 is True
16420 is True
13352 is True
11184 is True
3872 is True
8288 is True
17296 is False
20816 is True
11628 is True
17688 is True
12856 is True
19400 is True
8804 is True
16420 is True
13352 is True
11184 is True
3872 is True
8288 is True
17296 is True
20816 is True
11628 is True
17688 is True
12856 is True
19400 is True
Thread count: 12
Time elapsed: 3
cls;
$stopwatch = [system.diagnostics.stopwatch]::StartNew();
#region Runspace Pool
[runspacefactory]::CreateRunspacePool() | Out-Null;
$SessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault();
$RunspacePool = [runspacefactory]::CreateRunspacePool(
1, #Min Runspaces
16 #Max Runspaces
);
$RunspacePool.Open();
#endregion Runspace pool
$threads = New-Object System.Collections.ArrayList;
$servers = @("goodServer1", "goodServer2", "badServer1", "goodServer3");
foreach ($server in $servers)
{
$PowerShell = [powershell]::Create();
$PowerShell.RunspacePool = $RunspacePool;
[void]$PowerShell.AddScript({
Param ($server, $portNumber)
[pscustomobject]@{
server = $server
portNumber = $portNumber
} | Out-Null
Function testPort ($server, $portNumber)
{
$testPort = New-Object System.Net.Sockets.TCPClient # -ArgumentList $server, 3389;
$testPort.SendTimeout = 3;
try
{
$testPort.Connect($server, $portNumber);
}
catch
{
#do nothing;
}
$result = $testPort.Connected;
$testPort.Close();
$dateTime = ([DateTime]::Now.ToString());
return "$server|testPort|$result|$dateTime"; # server | function | result | DateTime
}
testPort -server $server -portNumber $portNumber;
}) # end of add script
$portNumber = "3389";
$PowerShell.AddParameter('server', $server).AddParameter('portNumber', $portNumber) | Out-Null;
$returnVal = $PowerShell.BeginInvoke();
$temp = "" | Select PowerShell,returnVal;
$temp.PowerShell = $PowerShell;
$temp.returnVal = $returnVal;
$threads.Add($Temp) | Out-Null;
$PowerShell = [powershell]::Create();
$PowerShell.RunspacePool = $RunspacePool;
[void]$PowerShell.AddScript({
Param ($server, $shareName, $timeOutInMs)
[pscustomobject]@{
server = $server
shareName = $shareName
timeOutInMs = $timeOutInMs
} | Out-Null
Function testShare ($server, $shareName, $timeOutInMs)
{
$cSharp =
@'
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace cSharp7
{
public class cSharpClass
{
public bool verifyDirectoryExists(string uri, int timeoutInMs)
{
var task = new Task<bool>(() =>
{
var dir = new DirectoryInfo(uri);
return dir.Exists;
});
task.Start();
return task.Wait(timeoutInMs) && task.Result;
}
public bool verifyFileExists(string uri, int timeoutInMs)
{
var task = new Task<bool>(() =>
{
var fi = new FileInfo(uri);
return fi.Exists;
});
task.Start();
return task.Wait(timeoutInMs) && task.Result;
}
}
}
'@
$assemblies = ("System", "System.Collections", "System.ComponentModel", "System.Data", "System.Drawing", "System.Linq", "System.Threading.Tasks", "System.Windows.Forms", "System.Management.Automation", "System.Security", "System.Threading", "System.Collections.Concurrent", "System.Security.Principal", "System.Management", "System.IO", "System.Collections");
Add-Type -TypeDefinition $cSharp -ReferencedAssemblies $assemblies -Language CSharp;
$directoryExists = New-Object CSharp7.cSharpClass;
$path = "\\" + $server + "\" + $shareName;
try
{
$result = $directoryExists.verifyDirectoryExists($path, $timeOutInMs); # has a 2 minute timeout period, needs an asynchronous thread with a timeout period
#Write-Host $result;
}
catch
{
# do nothing
}
$dateTime = ([DateTime]::Now.ToString());
return "$server|testShare|$result|$dateTime"; # server | function | result | DateTime
}
testShare -server $server -shareName $shareName -timeOutInMs $timeOutInMs;
}) # end of add script
$shareName = "c$";
$timeOutInMs = "3000";
$PowerShell.AddParameter('server', $server).AddParameter('shareName', $shareName).AddParameter('timeOutInMs', $timeOutInMs) | Out-Null;
$returnVal = $PowerShell.BeginInvoke();
$temp = "" | Select PowerShell,returnVal;
$temp.PowerShell = $PowerShell;
$temp.returnVal = $returnVal;
$threads.Add($Temp) | Out-Null;
$PowerShell = [powershell]::Create();
$PowerShell.RunspacePool = $RunspacePool;
[void]$PowerShell.AddScript({
Param ($server, $pingCount)
[pscustomobject]@{
server = $server
pingCount = $pingCount
} | Out-Null
Function testPing ($server, $pingCount)
{
try
{
$result = Test-Connection $server -Count $pingCount -Quiet;
}
catch
{
# do nothing
}
$dateTime = ([DateTime]::Now.ToString());
return "$server|testPing|$result|$dateTime"; # server | function | result | DateTime
}
testPing -server $server -pingCount $pingCount;
}) # end of add script
$pingCount = "1";
$PowerShell.AddParameter('server', $server).AddParameter('pingCount', $pingCount) | Out-Null;
$returnVal = $PowerShell.BeginInvoke();
$temp = "" | Select PowerShell,returnVal;
$temp.PowerShell = $PowerShell;
$temp.returnVal = $returnVal;
$threads.Add($Temp) | Out-Null;
}
$completed = $false;
while ($completed -eq $false)
{
$completed = $true;
foreach ($thread in $threads)
{
$endInvoke = $thread.PowerShell.EndInvoke($thread.returnVal);
$endInvoke;
$threadHandle = $thread.returnVal.AsyncWaitHandle.Handle;
$threadIsCompleted = $thread.returnVal.IsCompleted;
#Write-Host "$threadHandle is $threadIsCompleted";
if ($threadIsCompleted -eq $false)
{
$completed = $false;
}
}
Write-Host "";
sleep -Milliseconds 500;
}
foreach ($thread in $threads)
{
$thread.PowerShell.Dispose();
}
$stopwatch.Stop();
Write-Host "";
Write-Host "Thread count:" $threads.Count;
Write-Host "Time elapsed:" $stopwatch.Elapsed.Seconds;
Test-Path
? - person Santiago Squarzon   schedule 30.04.2021