J'ai un script PowerShell 1.0 pour ouvrir tout un tas d'applications. Le premier est une machine virtuelle et les autres sont des applications de développement. Je souhaite que la machine virtuelle termine le démarrage avant que le reste des applications ne soit ouvert.
En bash je pourrais juste dire "cmd1 && cmd2"
C'est ce que j'ai.
C:\Applications\VirtualBox\vboxmanage startvm superdooper
&"C:\Applications\NetBeans 6.5\bin\netbeans.exe"
Normalement, pour les commandes internes, PowerShell attend avant de lancer la commande suivante. Une exception à cette règle concerne les fichiers EXE externes basés sur un sous-système Windows. La première astuce consiste à créer un pipeline vers Out-Null
comme suit:
Notepad.exe | Out-Null
PowerShell attendra la fin du processus Notepad.exe avant de continuer. C'est astucieux mais assez subtil à lire après avoir lu le code. Vous pouvez également utiliser Start-Process avec le paramètre -Wait:
Start-Process <path to exe> -NoNewWindow -Wait
Si vous utilisez la version des extensions de communauté PowerShell, celle-ci est:
$proc = Start-Process <path to exe> -NoWindow
$proc.WaitForExit()
Une autre option de PowerShell 2.0 consiste à utiliser un travail d’arrière-plan:
$job = Start-Job { invoke command here }
Wait-Job $job
Receive-Job $job
Outre l'utilisation de Start-Process -Wait
, le fait de canaliser la sortie d'un fichier exécutable fera attendre Powershell. En fonction des besoins, je dirigerai généralement vers Out-Null
, Out-Default
, Out-String
ou Out-String -Stream
. Here est une longue liste de quelques autres options de sortie.
# Saving output as a string to a variable.
$output = ping.exe example.com | Out-String
# Filtering the output.
ping stackoverflow.com | where { $_ -match '^reply' }
# Using Start-Process affords the most control.
Start-Process -Wait SomeExecutable.com
Les opérateurs de style CMD/Bash auxquels vous avez fait référence (&, &&, ||) me manquent. Il semble que nous devions être plus verbeux avec Powershell .
Il suffit d'utiliser "Wait-process":
"notepad","calc","wmplayer" | ForEach-Object {Start-Process $_} | Wait-Process ;dir
la tâche est finie
Certains programmes ne traitent pas très bien le flux de sortie. L'utilisation de la fonction pipe to Out-Null
peut ne pas le bloquer.
Et Start-Process
a besoin du commutateur -ArgumentList
pour passer des arguments, ce qui n’est pas très pratique.
Il y a aussi une autre approche.
$exitCode = [Diagnostics.Process]::Start(<process>,<arguments>).WaitForExit(<timeout>)
Si vous utilisez Start-Process <path to exe> -NoNewWindow -Wait
Vous pouvez également utiliser l'option -PassThru
pour faire écho à la sortie.
Y compris l'option -NoNewWindow
me donne une erreur: Start-Process : This command cannot be executed due to the error: Access is denied.
La seule façon de le faire fonctionner était d'appeler:
Start-Process <path to exe> -Wait
En allant plus loin, vous pouvez même analyser à la volée
par exemple.
& "my.exe" | %{
if ($_ -match 'OK')
{ Write-Host $_ -f Green }
else if ($_ -match 'FAIL|ERROR')
{ Write-Host $_ -f Red }
else
{ Write-Host $_ }
}