A partir de PowerShell 7.2.1, Wait-Process
lorsqu'il est donné multiple attend invariablement tous d'entre eux de se terminer avant de revenir, ce qui peut introduire un problème de sécurité. -Any
de manière à n'attendre que n'importe lequel parmi eux, le sujet de Proposition GitHub #16972 ce qui simplifierait la solution à Wait-Process -Any -Id $pApp1.id, $pApp2.id
Délégation de l'attente de la sortie des processus à filetage / arrière-plan emplois évite d'avoir recours à une solution basée sur des événements ou des sondages périodiques.
# Start all processes asynchronously and get process-information
# objects for them.
$allPs = 'app1', 'app2' | ForEach-Object { Start-Process -PassThru $_ }
# Start a thread job for each process that waits for that process to exit
# and then pass the process-info object for the terminated process through.
# Exit the overall pipeline once the first output object from one of the
# jobs is received.
$terminatedPs = $allPs |
ForEach-Object { Start-ThreadJob { $ps = $using:_; Wait-Process -Id $ps.Id; $ps } } |
Receive-Job -Wait |
Select-Object -First 1
Write-Verbose -Verbose "Process with ID $($terminatedPs.Id) exited."
exit 1
Note :
-
J'utilise le Start-ThreadJob
qui offre une solution légère et beaucoup plus rapide. filetage -alternative aux tâches d'arrière-plan régulières basées sur les processus enfants, créées avec la commande Start-Job
. Il est livré avec PowerShell (Core) 7+ et en Windows PowerShell peut être installé à la demande avec, par exemple, Install-Module ThreadJob -Scope CurrentUser
. Dans la plupart des cas, les threads sont le meilleur choix, à la fois pour les performances et pour la fidélité au type - voir la section inférieure de la page cette réponse pourquoi.
-
Si Start-ThreadJob
n'est pas disponible pour vous / ne peut pas être installé, il suffit de le substituer Start-Job
dans le code ci-dessus.
PowerShell (Core) 7+ -seule solution avec ForEeach-Object -Parallel
:
PowerShell 7.0 a introduit la fonction -Parallel
au paramètre ForEach-Object
qui, en substance, apporte le parallélisme basé sur les threads à l'interface de l'ordinateur. pipeline Il s'agit d'un moyen de créer plusieurs tâches threads implicites, une pour chaque objet d'entrée du pipeline, qui émettent leur sortie directement vers le pipeline (bien que dans un ordre non garanti).
Par conséquent, la solution simplifiée suivante est possible :
# Start all processes asynchronously and get process-information
# objects for them.
$allPs = 'app1', 'app2' | ForEach-Object { Start-Process -PassThru $_ }
$terminatedPs = $allPs |
ForEach-Object -Parallel { $_ | Wait-Process; $_ } |
Select-Object -First 1
Write-Verbose -Verbose "Process with ID $($terminatedPs.Id) exited."
exit 1