234 votes

Comment dire à PowerShell d'attendre la fin de chaque commande avant de lancer la suivante ?

J'ai un script PowerShell 1.0 pour simplement ouvrir un groupe d'applications. La première est une machine virtuelle et les autres sont des applications de développement. Je veux que la machine virtuelle finisse de démarrer avant que le reste des applications ne soient ouvertes.

En bash, je pourrais simplement dire "cmd1 && cmd2"

C'est ce que j'ai...

C:\Applications\VirtualBox\vboxmanage startvm superdooper
    &"C:\Applications\NetBeans 6.5\bin\netbeans.exe"

401voto

Keith Hill Points 73162

Normalement, pour les commandes internes, PowerShell attend avant de lancer la commande suivante. Une exception à cette règle est l'EXE externe basé sur le sous-système Windows. La première astuce est de canaliser vers Out-Null comme ça :

Notepad.exe | Out-Null

PowerShell attendra que le processus Notepad.exe ait été quitté avant de poursuivre. C'est très pratique mais assez subtil à comprendre en lisant 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 PowerShell Community Extensions, c'est le cas :

$proc = Start-Process <path to exe> -NoNewWindow -PassThru
$proc.WaitForExit()

Une autre option de PowerShell 2.0 consiste à utiliser un travail en arrière-plan :

$job = Start-Job { invoke command here }
Wait-Job $job
Receive-Job $job

3 votes

C'est ma faute. Start-Process -Wait fonctionne très bien, mais maintenant je vois que ce n'est pas ce que je cherchais... Je cherche en fait à attendre que le vm finisse de démarrer. J'imagine que cela va être difficile. Je suppose que je vais devoir trouver un nouveau fil pour cela. Merci mais.

8 votes

Brillant, | out-null a fait exactement ce dont j'avais besoin. J'ai essayé d'utiliser Start-Job mais comme je passe les résultats des fonctions en paramètres, il est devenu un peu skitzoïde, et je n'ai pas pu utiliser la dernière suggestion...

6 votes

Par ailleurs, si vous avez besoin de passer plusieurs arguments avec -ArgumentList en les séparant par des virgules comme -ArgumentList /D=test,/S .

53voto

Nathan Hartley Points 1115

En plus d'utiliser Start-Process -Wait Si l'on fait suivre la sortie d'un exécutable, Powershell attendra. En fonction du besoin, je vais typiquement envoyer la sortie à Out-Null , Out-Default , Out-String ou Out-String -Stream . Ici est une longue liste d'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 que vous avez mentionnés (&, &&, ||) me manquent. Il semble que nous devons être plus verbeux avec Powershell .

0 votes

C'est une très bonne solution si vous avez besoin d'analyser la sortie !

1 votes

Mise en évidence Out-xxxx La liste des redirecteurs m'a rapidement permis de comprendre pourquoi je devais utiliser Out-Default au lieu de Out-Null puisque j'avais besoin de conserver la sortie console.

0 votes

Notez que pas de un travail supplémentaire est nécessaire pour exécuter console de manière synchrone - comme dans tout shell, c'est le comportement par défaut. La tuyauterie vers Out-String modifie la sortie à un simple, multi-ligne alors que PowerShell retourne par défaut une chaîne de caractères matrice de lignes . Start-Process devrait être évité pour les applications de console (à moins que vous ne souhaitiez vraiment les exécuter dans une nouvelle fenêtre ) parce que vous ne serez pas en mesure de capturer ou de rediriger leur sortie.

14voto

Flaviofire Points 1

Il suffit d'utiliser "Wait-process" :

"notepad","calc","wmplayer" | ForEach-Object {Start-Process $_} | Wait-Process ;dir

le travail est fait

8voto

Sandy Chapman Points 831

Si vous utilisez Start-Process <path to exe> -NoNewWindow -Wait

Vous pouvez également utiliser le -PassThru pour faire écho à la sortie.

2 votes

Notez que -PassThru ne fait pas écho sortie (par définition, une application qui n'est pas une console ne produit pas de sortie console), elle produit un fichier System.Diagnostics.Process qui représente le processus nouvellement lancé, afin que vous puissiez examiner ses propriétés et attendre qu'il se termine plus tard.

6voto

ifree Points 64

Certains programmes ne peuvent pas traiter le flux de sortie très bien, en utilisant pipe pour Out-Null ne peut pas le bloquer.
Et Start-Process besoins de l -ArgumentList pour passer des arguments, pas si pratique.
Il existe également une autre approche.

$exitCode = [Diagnostics.Process]::Start(<process>,<arguments>).WaitForExit(<timeout>)

2 votes

Comment les arguments multiples fonctionnent-ils dans cet appel ? comment sont-ils délimités ? comment gérer les diverses chaînes de caractères imbriquées ? ty !

1 votes

@AnneTheAgile doc utiliser l'espace pour séparer les arguments, pour l'échappement des caractères utiliser la barre oblique inverse.

1 votes

Ty @ifree, j'ai réussi à faire fonctionner testcomplete de cette façon ! J'ai utilisé des guillemets simples autour de la liste des arguments délimités par des espaces.[1] ; mais maintenant echo $exitcode=false, ce qui n'était pas mon code de retour du processus ? [1] $exitCode = [Diagnostics.Process]::Start( "c : \Program Fichiers (x86) \SmartBear\TestComplete 10 \Bin\TestComplete.exe " ,'"c : \Users\ME\Documents\TestComplete 10 Projets \hig4TestProject1\hig4TestProject1.pjs " /run /projet:monProj/test : "KeywordTests|zTdd1_Good" /exit' ).WaitForExit(60)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X