web-dev-qa-db-fra.com

Le script Powershell reste bloqué et ne se ferme pas lorsqu'il est appelé depuis un fichier de commandes

J'ai un script PowerShell qui se connecte à un site Web et analyse les données renvoyées (il s'agit d'importer un fichier SQL précédemment téléchargé dans la base de données du site Web). Le script PowerShell utilise wget, quelque chose que je pourrais remplacer par une fonction native ultérieurement.

Le processus d'importation est intégré à un script exécuté par un programme tiers appelé scriptFTP .

Le script fonctionne correctement lorsque je l’appelle à partir d’un seul fichier .bat comme suit:

powershell  "& "C:\data\etc\run_import_script.ps1"
exit %ERRORLEVEL%

Cependant, lorsque j'appelle ce fichier .bat à partir du contexte ScriptFTP, les événements suivants se produisent:

  • Le script PowerShell est exécuté. Je l'ai confirmé en m'envoyant moi-même un courrier électronique chaque fois que le script d'importation à distance était appelé.
  • PowerShell ne semble pas se fermer et l'exécution du script est bloquée. Je peux toujours annuler le tout en utilisant Ctrl + C mais les commandes suivantes ne sont jamais exécutées.

Lorsque je modifie le fichier de commandes comme suit:

start powershell  "& "C:\data\etc\run_import_script.ps1"
exit %ERRORLEVEL%

il fonctionne et exécute le script PowerShell dans une nouvelle console, mais je ne peux pas saisir le niveau d'erreur renvoyé par PowerShell. 

J'ai essayé d'appeler directement PowerShell à partir de ScriptFTP, en contournant le fichier de commandes, mais avec le même résultat: il reste bloqué.

Toute sortie du script PowerShell utilisant Write-Output ou Write-Host n'est pas affichée.

Tous les programmes fonctionnent sous le même utilisateur, moi. 

Quelqu'un a-t-il des idées sur ce qu'il faut faire?

33
Pekka 웃

Essayez d’ajouter le paramètre/WAIT. Il laissera le fichier .bat en attente jusqu'à la fin du script PowerShell.

START /WAIT powershell "& "C:\data\etc\run_import_script.ps1"
16
aphoria

Cette variante pourrait fonctionner pour vous.

powershell -NoProfile -Command "C:\data\etc\run_import_script.ps1; exit $LASTEXITCODE" < NUL

Tiré de http://thepowershellguy.com/blogs/posh/archive/2008/05/20/hey-powershell-guy-how-can-i-run-a-powershell-script-from-cmd-exe- and-return-an-errorlevel.aspx

22
Jason Swager

D'après mon expérience, PowerShell.exe peut facilement exécuter des scripts à partir d'un fichier de commandes ou d'un script Shell de manière prévisible à l'aide du commutateur -File. Il n'est pas nécessaire d'utiliser la commande Démarrer.

La chose importante à faire est d’ajouter 

< nul

à la ligne de commande depuis un fichier batch. Ma recherche a montré que PowerShell exécute les commandes du script indiqué par le commutateur -File et attend ensuite des commandes PowerShell supplémentaires à partir de l'entrée standard (ma brève expérimentation avec le commutateur -Command a démontré un comportement similaire). En redirigeant l'entrée standard vers zéro, une fois que PowerShell a terminé l'exécution du script et "lit la fin du fichier" à partir de l'entrée standard, PowerShell se ferme.

Lorsque vous appelez PowerShell à partir de Cygwin, utilisez 

< /dev/null

Par exemple, j'ai exécuté des scripts PowerShell à partir de Cygwin à l'aide de variables Shell, comme ceci: 

PowerShell.exe -ExecutionPolicy RemoteSigned -File $_powershellscriptpath $_firstscriptparameter < /dev/null

S'il vous plaît poster un commentaire si votre expérience varie de la mienne .- Gordon

16
Gordon Smith

Nous avons eu un problème similaire. Nous voulions appeler une application powershell à partir d'un logiciel qui ne contenait qu'une boîte pour saisir "Command" et "Paramètres", mais le powershell a été exécuté avec succès (le fichier affecté a été mis à jour.)

Finalement, mon collègue m'a aidé à comprendre Le commandement doit être:

C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe 

Et paramètres:

-ExecutionPolicy unrestricted -Command "& {C:\scripts\apps\EDI\Test.ps1; [Environment]::Exit(1)}"

Dans notre cas, il était important d'utiliser [Environment]::Exit(1) plutôt que Exit 1. Je crois que Exit était simplement en train de terminer le script, pas de fermer Powershell lui-même.

9
user2733913

Si vous souhaitez capturer la sortie des commandes powershell.exe, vous pouvez également utiliser le paramètre/B pour forcer le processus à s'exécuter dans le shell same command.

Nous venons de voir un cas très étrange de ce problème. Un fichier de commandes contenant l'appel powershell.exe -command ... a fonctionné correctement localement mais s'est bloqué comme décrit ci-dessus lorsque le fichier de commandes a été exécuté dans le contexte d'une commande msdeploy -postSync. Après avoir essayé avec process.Kill() pour forcer PowerShell à quitter, nous nous sommes allumés sur l'utilisation de START /WAIT /B PowerShell.exe ..

Aucune idée pourquoi cela devrait fonctionner, mais ça marche ...

2
Stephen Connolly

SI c’est exactement ce qui se trouve dans votre fichier, c’est parce que vos citations ne correspondent pas. Powershell attend le dernier devis.

1
WebWeasel

vous pouvez simplement ajouter une commande 'exit' à la fin du script .ps1 (ou toute autre variante de fin de processus que vous souhaitez). Powershell continuera à s'exécuter à la fin du script car il n'a pas été indiqué à l'utilisateur de se terminer (lorsqu'il est exécuté dans PS ou ISE, il se termine automatiquement à la fin du script, mais pas lorsqu'il est exécuté via le shell DOS).

0
Tim

PowerShell a, du moins ce que j’envisage, un comportement étrange lorsqu’il est invoqué de cette manière. En bref, les arguments de ligne de commande transmis à powershell.exe ne sont pas considérés comme des scripts à exécuter. Au lieu de cela, il les traite comme une commande à exécuter. En effet, la valeur par défaut de powershell.exe est -command - voir powershell.exe /? pour plus d'informations.

C:\>powershell "'Hello'"
Hello

Ce que vous devez faire, c'est construire une chaîne d'entrée intelligente pour "générer" le script que vous souhaitez exécuter:

C:\>powershell ". .\test.ps1"
Hello, World!

En ce qui concerne le résultat, une fois que le script fonctionne correctement, il ne vous reste plus qu'à capturer STDOUT ou tout ce qui finira par correspondre à votre script.

Exemple complet

test.bat

@echo off
powershell.exe ". .\test.ps1"

test.ps1

"Hello, World!"

Invoquer la commande:

test.bat > test.txt

Et vérifiez que la sortie a été capturée:

C:\>type test.txt
Hello, World!
0
Goyuix

J'ai eu le problème exact, nous essayions d'intégrer les scripts Power Shell dans un autre système et cela continuait à donner une erreur de délai d'attente. Probablement à cause du problème mentionné par Gordon Smith, sa solution pourrait fonctionner. Mais pour moi, je préfère avoir le contrôle total de mon script depuis le script lui-même et ne pas dépendre de la façon dont il est appelé.

$ pid est construit en variable avec le PID. La liste ci-dessous mettra fin au processus actuel de PowerShell et laissera les autres intactes. De cette façon, tout le monde peut appeler votre script normalement et il fonctionnera comme prévu.

Stop-Process $pid
0
sheldonj22

Le problème que je parie est que le processus de Powershell continue de s'exécuter après l'exécution du script . Cela signifie qu'il n'est pas sorti et qu'il n'y a donc pas de code de sortie. J'ai un problème similaire lorsque j'essaie d'exécuter un script Powershell à partir de C # qui effectue des tâches une fois terminé, sauf qu'il ne se termine jamais ...

Hacky, mais la seule solution que j'ai trouvée consiste à mettre Stop-Process -processname powershell à la fin du script .ps1. Cela annule le processus PowerShell (et toutes les fenêtres PowerShell que vous avez ouvertes, malheureusement), mais semble fonctionner. Cela pourrait également fonctionner pour votre script.

0
Deadly-Bagel