webentwicklung-frage-antwort-db.com.de

Das Powershell-Skript bleibt hängen, wird nicht beendet, wenn es aus der Batchdatei aufgerufen wird

Ich habe ein PowerShell-Skript, das eine Verbindung zu einer Website herstellt und die zurückgegebenen Daten analysiert (es geht darum, eine zuvor hochgeladene SQL-Datei in die Datenbank der Website zu importieren). Das PowerShell-Skript verwendet wget, was ich später durch eine native Funktion ersetzen kann.

Der Importvorgang ist in ein Skript eingebettet, das von einem Drittanbieterprogramm namens scriptFTP ausgeführt wird.

Das Skript läuft einwandfrei, wenn ich es aus einer einzelnen .bat-Datei anrufe:

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

Wenn ich diese .bat-Datei aus dem größeren ScriptFTP-Kontext heraus anrufe, geschieht Folgendes:

  • Das PowerShell-Skript wird ausgeführt. Ich bestätigte, dass ich mir jedes Mal eine E-Mail schickte, wenn das Remote-Import-Skript aufgerufen wurde.
  • PowerShell scheint nicht zu beenden, und die Skriptausführung bleibt hängen. Ich kann das Ganze immer noch mit Strg + C abbrechen, aber die folgenden Befehle werden nie ausgeführt.

Wenn ich die Batchdatei folgendermaßen ändere:

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

it works, wobei das PowerShell-Skript in einer neuen Konsole ausgeführt wird, aber ich kann die von PowerShell zurückgegebene Fehlerstufe nicht ermitteln. 

Ich habe versucht, PowerShell direkt von ScriptFTP aus aufzurufen, wobei die Batchdatei umgangen wurde, aber mit dem gleichen Ergebnis: Es bleibt einfach hängen.

Alle Ausgaben, die das PowerShell-Skript mit Write-Output oder Write-Host ausführen soll, werden nicht angezeigt.

Alle Programme laufen unter demselben Benutzer, mir. 

Hat jemand eine Idee, was zu tun ist?

33
Pekka 웃

Versuchen Sie, den Parameter/WAIT hinzuzufügen. Dadurch bleibt die .bat so lange warten, bis das PowerShell-Skript abgeschlossen ist.

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

Diese Variante könnte für Sie funktionieren.

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

Entnommen aus 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

Meiner Erfahrung nach kann PowerShell.exe Skripts in einer Stapelverarbeitungsdatei oder einem Shell-Skript auf vorhersehbare Weise mithilfe des Befehls "File" ausführen. Der Startbefehl muss nicht verwendet werden.

Das Wichtigste ist das Anhängen 

< nul

zur Befehlszeile aus einer Batchdatei. Meine Nachforschungen haben gezeigt, dass PowerShell die Befehle in dem Skript ausführt, das über den Schalter "File" angegeben wird und wartet dann auf zusätzliche PowerShell-Befehle von der Standardeingabe (Mein kurzes Experimentieren mit dem -Befehlsschalter zeigte ein ähnliches Verhalten). Durch die Umleitung der Standardeingabe in nul wird PowerShell beendet, sobald PowerShell die Ausführung des Skripts abgeschlossen hat und das Ende der Datei "liest".

Wenn Sie PowerShell von Cygwin aus aufrufen, verwenden Sie 

< /dev/null

Zum Beispiel habe ich PowerShell-Skripts von Cygwin aus mit Shell-Variablen wie folgt ausgeführt: 

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

Bitte posten Sie einen Kommentar, wenn Ihre Erfahrung von meiner abweicht .- Gordon

16
Gordon Smith

Wir hatten ein ähnliches Problem. Wir wollten eine Powershell-App von einer Software aufrufen, die nur eine Box für die Eingabe von "Befehl" und "Parameter" hatte, aber die Powershell lief erfolgreich (die betroffene Datei wurde aktualisiert)

Schließlich half mir mein Kollege, das herauszufinden Das Kommando muss sein:

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

Und Parameter:

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

In unserem Fall war es wichtig, [Environment]::Exit(1) anstelle von Exit 1 zu verwenden. Ich glaube, dass Exit einfach das Skript beendet, nicht Powershell sich selbst schließt.

9
user2733913

Wenn Sie die Ausgabe der powershell.exe-Befehle erfassen möchten, können Sie auch den Parameter/B verwenden, um die Ausführung des Prozesses in der Shell same command zu erzwingen.

Wir haben gerade ein sehr seltsames Beispiel dieses Problems gesehen. Eine Batchdatei, die den Aufruf powershell.exe -command ... enthält, wurde lokal ordnungsgemäß ausgeführt, aber wie oben beschrieben angehalten, wenn die Batchdatei im Kontext eines Befehls msdeploy -postSync ausgeführt wurde. Nachdem wir mit process.Kill() experimentiert haben, um das Beenden von PowerShell zu erzwingen, haben wir uns mit START /WAIT /B PowerShell.exe .. vertraut gemacht.

Keine Ahnung, warum das funktionieren sollte, aber es tut ...

2

WENN genau das in Ihrer Datei ist, liegt das daran, dass Sie die Anführungszeichen nicht übereinstimmen. Powershell wartet auf das letzte Zitat.

1
WebWeasel

sie können einfach einen 'exit'-Befehl am Ende des .ps1-Skripts hinzufügen (oder eine beliebige Variante der Prozessbeendigung, die Sie wünschen). Powershell wird am Ende des Skripts weiter ausgeführt, da es nicht aufgefordert wurde, das Programm zu beenden (wenn es in PS oder ISE ausgeführt wird, wird es am Ende des Skripts automatisch beendet, jedoch nicht, wenn es über die DOS-Shell ausgeführt wird).

0
Tim

PowerShell hat zumindest ein merkwürdiges Verhalten, wenn es auf diese Weise aufgerufen wird. Kurz gesagt, es behandelt die Befehlszeilenargumente, die an powershell.exe übergeben werden, nicht als auszuführende Skripts. Stattdessen werden sie als Befehl zum Ausführen behandelt. Dies liegt daran, dass die Standardeinstellung für powershell.exe -command lautet - siehe powershell.exe /? für weitere Infos.

C:\>powershell "'Hello'"
Hello

Was Sie tun müssen, ist, eine clevere Eingabezeichenfolge zu erstellen, um das Skript, das Sie ausführen möchten, zu "quellen":

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

Wenn Sie das Skript korrekt ausgeführt haben, sollten Sie lediglich STDOUT erfassen oder was auch immer zu Ihrem Skript passt.

Vollständiges Beispiel

test.bat

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

test.ps1

"Hello, World!"

Rufen Sie den Befehl auf:

test.bat > test.txt

Und vergewissern Sie sich, dass die Ausgabe erfasst wurde:

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

Ich hatte das genaue Problem, wir versuchten, Power Shell-Skripts in ein anderes System zu integrieren, und es gab immer einen Timeout-Fehler. Wahrscheinlich wegen des von Gordon Smith erwähnten Problems könnte seine Lösung funktionieren. Mir ist es jedoch lieber, wenn ich mein Skript vollständig aus dem Skript selbst heraus kontrolliere und nicht auf die Art und Weise, wie es aufgerufen wird.

$ pid ist in eine Variable mit der PID eingebaut. Das Folgende beendet den aktuellen Powershell-Prozess und lässt die anderen intakt. Auf diese Weise kann jeder Ihr Skript als normal aufrufen und es funktioniert wie erwartet.

Stop-Process $pid
0
sheldonj22

Ich wette, das Problem ist, dass der Powershell-Prozess nach Ausführung des Skripts ausgeführt wird. Dies bedeutet, dass es nicht beendet wurde und daher kein Beendigungscode vorhanden ist. Ich habe ein ähnliches Problem, wenn ich versuche, ein Powershell-Skript von C # auszuführen, das nach Abschluss der Arbeit alles erledigt, es sei denn, es wird nie beendet.

Hacky, aber die einzige Lösung, die ich gefunden habe, ist, Stop-Process -processname powershell am Ende des .ps1-Skripts zu setzen. Dies beendet den PowerShell-Prozess (und alle PowerShell-Fenster, die Sie leider geöffnet haben), scheint jedoch zu funktionieren. Könnte auch für Ihr Skript funktionieren.

0
Deadly-Bagel