Hinweis: Der Befehl in der Frage verwendet Start-Process
, wodurch die direkte Erfassung der Ausgabe des Zielprogramms verhindert wird. Im Allgemeinen verwenden Sie keine Start-Process
Konsolenanwendungen synchron auszuführen - nur invoke sie direkt , wie in jeder Schale. Auf diese Weise bleibt die Anwendung mit den Standard-Streams der aufrufenden Konsole verbunden, sodass die Ausgabe durch einfache Zuweisung erfasst werden $output = netdom ...
kann (siehe unten).
Grundsätzlich funktioniert das Erfassen der Ausgabe von externen Dienstprogrammen genauso wie bei PowerShell-nativen Befehlen (möglicherweise möchten Sie eine Auffrischung zum Ausführen externer Tools ):
$cmdOutput = <command> # captures the command's success stream / stdout
Man beachte , dass $cmdOutput
ein empfängt Array von Objekten , wenn <command>
produziert mehr als 1 Ausgangsobjekt , das in dem Fall eines externen Programms bedeutet einen String - Array enthält die Ausgabe der Programmzeilen .
Wenn Sie $cmdOutput
immer eine einzelne - möglicherweise mehrzeilige - Zeichenfolge erhalten möchten , verwenden Sie
$cmdOutput = <command> | Out-String
So erfassen Sie die Ausgabe in einer Variablen und drucken auf dem Bildschirm :
<command> | Tee-Object -Variable cmdOutput # Note how the var name is NOT $-prefixed
Wenn <command>
es sich um ein Cmdlet oder eine erweiterte Funktion handelt, können Sie den allgemeinen Parameter
-OutVariable
/ verwenden-ov
:
<command> -OutVariable cmdOutput # cmdlets and advanced functions only
Beachten Sie, dass mit -OutVariable
, im Gegensatz zu den anderen Szenarien $cmdOutput
ist immer eine Sammlung , auch wenn nur ein Objekt ausgegeben wird. Insbesondere wird eine Instanz vom Array-ähnlichen [System.Collections.ArrayList]
Typ zurückgegeben.
In dieser GitHub-Ausgabe finden Sie eine Diskussion dieser Diskrepanz.
Verwenden Sie zum Erfassen der Ausgabe mehrerer Befehle entweder einen Unterausdruck ( $(...)
) oder rufen Sie einen Skriptblock ( { ... }
) mit &
oder auf .
:
$cmdOutput = $(<command>; ...) # subexpression
$cmdOutput = & {<command>; ...} # script block with & - creates child scope for vars.
$cmdOutput = . {<command>; ...} # script block with . - no child scope
Beachten Sie, dass die allgemeine Notwendigkeit, &
einem einzelnen Befehl (dessen Aufruf / Pfad) in Anführungszeichen steht (z. B.), $cmdOutput = & 'netdom.exe' ...
nicht mit externen Programmen an sich zusammenhängt (dies gilt auch für PowerShell-Skripte), sondern eine Syntaxanforderung ist : PowerShell Analysiert eine Anweisung, die standardmäßig mit einer Zeichenfolge in Anführungszeichen im Ausdrucksmodus beginnt , während der Argumentmodus zum Aufrufen von Befehlen (Cmdlets, externe Programme, Funktionen, Aliase) erforderlich ist &
.
Der Hauptunterschied zwischen $(...)
und & { ... }
/ und . { ... }
besteht darin, dass erstere alle Eingaben im Speicher sammeln, bevor sie als Ganzes zurückgegeben werden, während letztere die Ausgabe streamen , die für die Eins-zu-Eins-Pipeline-Verarbeitung geeignet ist.
Weiterleitungen funktionieren grundsätzlich genauso (siehe jedoch die folgenden Einschränkungen):
$cmdOutput = <command> 2>&1 # redirect error stream (2) to success stream (1)
Bei externen Befehlen funktioniert jedoch mit größerer Wahrscheinlichkeit Folgendes wie erwartet:
$cmdOutput = cmd /c <command> '2>&1' # Let cmd.exe handle redirection - see below.
Überlegungen zu externen Programmen:
Externe Programme geben , da sie außerhalb des PowerShell-Typsystems ausgeführt werden, immer nur Zeichenfolgen über ihren Erfolgsstrom (stdout) zurück.
Wenn die Ausgabe mehr als eine Zeile enthält , teilt PowerShell sie standardmäßig in ein Array von Zeichenfolgen auf . Genauer gesagt werden die Ausgabezeilen in einem Array vom Typ gespeichert, [System.Object[]]
dessen Elemente Zeichenfolgen ( [System.String]
) sind.
Wenn die Ausgabe eine einzelne , möglicherweise mehrzeilige Zeichenfolge sein soll , leiten Sie Folgendes anOut-String
:
$cmdOutput = <command> | Out-String
Das Umleiten von stderr zu stdout mit2>&1
, um es auch als Teil des Erfolgsstroms zu erfassen, ist mit folgenden Einschränkungen verbunden :
Um 2>&1
stdout und stderr an der Quelle zusammenzuführen , lassen Sie cmd.exe
die Umleitung mit den folgenden Redewendungen ablaufen:
$cmdOutput = cmd /c <command> '2>&1' # *array* of strings (typically)
$cmdOutput = cmd /c <command> '2>&1' | Out-String # single string
cmd /c
wird cmd.exe
mit Befehl aufgerufen <command>
und nach <command>
Beendigung beendet.
- Beachten Sie die einfachen Anführungszeichen, um
2>&1
sicherzustellen, dass die Umleitung an cmd.exe
PowerShell übergeben und nicht von PowerShell interpretiert wird.
Beachten Sie, dass das Einbeziehen cmd.exe
bedeutet, dass die Regeln für das Escapezeichen von Zeichen und das Erweitern von Umgebungsvariablen standardmäßig zusätzlich zu den eigenen Anforderungen von PowerShell ins Spiel kommen. In PS v3 + können Sie spezielle Parameter --%
(das sogenannte Stop-Parsing-Symbol ) verwenden, um die Interpretation der verbleibenden Parameter durch PowerShell zu cmd.exe
deaktivieren , mit Ausnahme von Verweisen auf Umgebungsvariablen im Stil wie %PATH%
.
Da Sie mit diesem Ansatz stdout und stderr an der Quelle zusammenführen , können Sie in PowerShell nicht zwischen Zeilen mit stdout- und stderr-Ursprung unterscheiden . Wenn Sie diese Unterscheidung benötigen, verwenden Sie die PowerShell-eigene 2>&1
Umleitung - siehe unten.
Verwenden Sie die 2>&1
Umleitung von PowerShell, um festzustellen, welche Zeilen von welchem Stream stammen :
Die Stderr- Ausgabe wird als Fehlerdatensätze ( ) und nicht als Zeichenfolgen erfasst[System.Management.Automation.ErrorRecord]
, sodass das Ausgabearray eine Mischung aus Zeichenfolgen (jede Zeichenfolge repräsentiert eine Standardzeile) und Fehlerdatensätzen (jeder Datensatz repräsentiert eine Standardzeile) enthalten kann . Beachten Sie, dass auf Anforderung 2>&1
sowohl die Zeichenfolgen als auch die Fehlerdatensätze über den Erfolgsausgabestream von PowerShell empfangen werden .
In der Konsole werden die Fehlerdatensätze rot gedruckt , und der erste erzeugt standardmäßig eine mehrzeilige Anzeige in demselben Format, in dem der nicht terminierende Fehler eines Cmdlets angezeigt wird. nachfolgende Fehlersätze in rot gedruckt werden als gut, aber nur ihre Fehler drucken Nachricht , auf einer einzigen Zeile .
Bei der Ausgabe an die Konsole , die Saiten der Regel kommen zuerst in der Ausgangsanordnung, die durch die Fehlersätze gefolgt (zumindest bei einer Charge von stdout / stderr Linien Ausgang „zur gleichen Zeit“), aber, zum Glück, wenn Sie erfassen die Ausgabe Es ist richtig verschachtelt und verwendet dieselbe Ausgabereihenfolge, die Sie ohne erhalten würden 2>&1
. Mit anderen Worten: Bei der Ausgabe an die Konsole spiegelt die erfasste Ausgabe NICHT die Reihenfolge wider, in der stdout- und stderr-Zeilen vom externen Befehl generiert wurden.
Wenn Sie die gesamte Ausgabe in einer einzelnen Zeichenfolge mit erfassenOut-String
, fügt PowerShell zusätzliche Zeilen hinzu , da die Zeichenfolgendarstellung eines Fehlerdatensatzes zusätzliche Informationen wie location ( At line:...
) und category ( + CategoryInfo ...
) enthält. Seltsamerweise gilt dies nur für den ersten Fehlerdatensatz.
- Wenden Sie die
.ToString()
Methode auf jedes Ausgabeobjekt an, um dieses Problem zu umgehen, anstatt auf Folgendes zu verweisen Out-String
:
$cmdOutput = <command> 2>&1 | % { $_.ToString() }
;
In PS v3 + können Sie Folgendes vereinfachen:
$cmdOutput = <command> 2>&1 | % ToString
(Wenn die Ausgabe nicht erfasst wird, wird als Bonus auch beim Drucken auf der Konsole eine ordnungsgemäß verschachtelte Ausgabe erstellt.)
Alternativ können Sie die Fehleraufzeichnungen herausfiltern und an den Fehlerstrom von PowerShell senden mitWrite-Error
(als Bonus führt dies dazu, dass die Ausgabe auch beim Drucken auf der Konsole ordnungsgemäß verschachtelt wird, wenn die Ausgabe nicht erfasst wird):
$cmdOutput = <command> 2>&1 | ForEach-Object {
if ($_ -is [System.Management.Automation.ErrorRecord]) {
Write-Error $_
} else {
$_
}
}
Start-Process
diese Option nicht , um (per Definition externe) Konsolenanwendungen synchron auszuführen. Rufen Sie sie einfach direkt auf , wie in jeder Shell. zu wissen :netdom /verify $pc /domain:hosp.uhhg.org
. Auf diese Weise bleibt die Anwendung mit den Standard-Streams der aufrufenden Konsole verbunden, sodass die Ausgabe durch einfache Zuweisung erfasst werden kann$output = netdom ...
. Die meisten der unten angegebenen Antworten verzichten implizitStart-Process
zugunsten einer direkten Ausführung.