So geben Sie etwas in PowerShell aus

210

Ich führe ein PowerShell-Skript aus einer Batchdatei aus. Das Skript ruft eine Webseite ab und prüft, ob der Inhalt der Seite die Zeichenfolge "OK" ist.

Das PowerShell-Skript gibt eine Fehlerstufe an das Batch-Skript zurück.

Das Batch-Skript wird von ScriptFTP , einem FTP-Automatisierungsprogramm, ausgeführt. Wenn ein Fehler auftritt, kann ScriptFTP die vollständige Konsolenausgabe per E-Mail an den Administrator senden.

Im PowerShell-Skript möchte ich den Rückgabewert von der Website ausgeben, wenn er nicht "OK" ist, sodass die Fehlermeldung in der Konsolenausgabe und damit in der Statusmail enthalten ist.

Ich bin neu in PowerShell und nicht sicher, welche Ausgabefunktion ich dafür verwenden soll. Ich kann drei sehen:

  • Write-Host
  • Schreibausgabe
  • Schreibfehler

Was wäre das Richtige, um in das Windows-Äquivalent von zu schreiben stdout?

Pekka
quelle

Antworten:

196

PowerShell ist einfach etwas Schönes - und eine seiner größten Stärken. Zum Beispiel das gemeinsame Hallo, Welt! Anwendung wird auf eine einzige Zeile reduziert:

"Hello, World!"

Es erstellt ein Zeichenfolgenobjekt, weist den oben genannten Wert zu und ruft als letztes Element in der Befehlspipeline die .toString()Methode auf und gibt das Ergebnis STDOUT(standardmäßig) an aus. Eine Sache der Schönheit.

Die anderen Write-*Befehle sind spezifisch für die Ausgabe des Texts an die zugehörigen Streams und haben ihren Platz als solche.

Goyuix
quelle
9
Das ist nicht wirklich was passiert. Es ist ein String-Literal-Ausdruck und das einzige, was sich in seiner Pipeline befindet. Somit ist es gleichbedeutend mit "Hello, World!" | Out-Host. Out-HostAuf der anderen Seite werden Objekte zur Anzeige an den PowerShell-Host gesendet, und ihre Implementierung hängt vom Host ab. Der Konsolenhost sendet sie Out-Defaulttatsächlich an das Standardausgabe-Handle (das auf dem Weg durchläuft ). PowerShell ISE zeigt sie jedoch in seinem Ausgabebereich an, und andere Hosts können möglicherweise noch andere Aufgaben ausführen.
Joey
5
Objekte werden auch nicht blind in Zeichenfolgen konvertiert, sondern durchlaufen einen Formatierer, der entscheidet, was mit ihnen geschehen soll. Aus diesem Grund wird die Get-ChildItemAusgabe beispielsweise in Tabellenform angezeigt, und die Ergebnisse werden Format-Liststattdessen mit vielen Eigenschaften (z. B. WMI) verwendet.
Joey
120

Ich denke in diesem Fall benötigen Sie Write-Output .

Wenn Sie ein Skript wie haben

Write-Output "test1";
Write-Host "test2";
"test3";

Wenn Sie dann das Skript mit umgeleiteter Ausgabe aufrufen yourscript.ps1 > out.txt, werden Sie in der "out.txt" test2auf dem Bildschirm test1\ntest3\nangezeigt.

Beachten Sie, dass "test3" und die Write-Output-Zeile immer eine neue Zeile an Ihren Text anhängen und es in PowerShell keine Möglichkeit gibt, dies zu stoppen (dies echo -nist in PowerShell mit den nativen Befehlen unmöglich). Wenn Sie (die etwas einfach und leicht in möchten Bash ) Funktionalität echo -ndann sehen samthebest Antwort .

Wenn in einer Batchdatei ein PowerShell-Befehl ausgeführt wird, wird höchstwahrscheinlich der Befehl Schreiben / Ausgeben erfasst. Ich habe "lange Diskussionen" mit Systemadministratoren darüber geführt, was auf die Konsole geschrieben werden soll und was nicht. Wir haben uns jetzt darauf geeinigt, dass die einzigen Informationen, wenn das Skript erfolgreich ausgeführt wurde oder gestorben ist Write-Host, bearbeitet werden müssen und alles, was der Autor des Skripts über die Ausführung wissen muss (welche Elemente aktualisiert wurden, welche Felder festgelegt wurden usw.), abläuft zur Schreibausgabe. Auf diese Weise kann der Systemadministrator beim Senden eines Skripts leicht runthescript.ps1 >someredirectedoutput.txtauf dem Bildschirm sehen, ob alles in Ordnung ist. Senden Sie dann die "someredirectedoutput.txt" an die Entwickler zurück.

Naivisten
quelle
9

Ich denke, das Folgende ist eine gute Ausstellung von Echo vs. Write-Host . Beachten Sie, wie test () tatsächlich ein Array von Ints zurückgibt, nicht ein einziges Int, wie man leicht glauben könnte.

function test {
    Write-Host 123
    echo 456 # AKA 'Write-Output'
    return 789
}

$x = test

Write-Host "x of type '$($x.GetType().name)' = $x"

Write-Host "`$x[0] = $($x[0])"
Write-Host "`$x[1] = $($x[1])"

Terminalausgang der oben genannten:

123
x of type 'Object[]' = 456 789
$x[0] = 456
$x[1] = 789
user2426679
quelle
Ich kann mir das den ganzen Tag ansehen ... Aber warum wird $x = testnur gedruckt 123und nicht auch 456?
not2qubit
7

Sie können diese in Ihrem Szenario verwenden, da sie in die Standard-Streams schreiben (Ausgabe und Fehler). Wenn Sie die Ausgabe an ein anderes Commandlet weiterleiten, möchten Sie Write-Output verwenden , das schließlich in Write-Host endet .

Dieser Artikel beschreibt die verschiedenen Ausgabeoptionen: PowerShell O ist für die Ausgabe vorgesehen

GrayWizardx
quelle
1
Danke für den Link. Meine Güte, das ist kompliziert . Wenn Write-Host eine Art Endpunkt- oder Flushing-Funktion ist, werde ich versuchen, damit fortzufahren und Bericht zu erstatten.
Pekka
3
Write-Host "Found file - " + $File.FullName -ForegroundColor Magenta

Magenta kann einer der Enumeratorwerte für "System.ConsoleColor" sein - Schwarz, Dunkelblau, Dunkelgrün, DunkelCyan, Dunkelrot, Dunkelagenta, Dunkelgelb, Grau, Dunkelgrau, Blau, Grün, Cyan, Rot, Magenta, Gelb, Weiß.

Das + $File.FullNameist optional und zeigt, wie eine Variable in die Zeichenfolge eingefügt wird.

Jordanien
quelle
2

Sie können PowerShell einfach nicht dazu bringen, diese lästigen Zeilenumbrüche zu unterlassen. Es gibt kein Skript oder Cmdlet, das dies tut.

Natürlich ist Write-Host absoluter Unsinn, weil man nicht umleiten / weiterleiten kann! Sie müssen einfach Ihre eigenen schreiben:

using System;

namespace WriteToStdout
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args != null)
            {
                Console.Write(string.Join(" ", args));
            }
        }
    }
}

Z.B

PS C:\> writetostdout finally I can write to stdout like echo -n
finally I can write to stdout like echo -nPS C:\>
samthebest
quelle
Sie könnten dies in Powershell selbst tun. [System.Console] :: Write ("stringy") Sie können es jedoch in Powershell überhaupt nicht umleiten.
Nicholi
1
Sicher kannst du. Siehe diese Frage
Slogmeister Extraordinaire
1

Was wäre das Richtige, um in das Windows-Äquivalent von stdout zu schreiben?

In Wirkung , aber sehr leider sowohl Windows Powershell und Powershell - Core ab v7.0, senden alle ihre 6 (!) Ausgangsströme auf stdout , wenn genannt von außen , über Powershell CLI .

  • In diesem GitHub-Problem finden Sie eine Diskussion dieses problematischen Verhaltens, das aus Gründen der Abwärtskompatibilität wahrscheinlich nicht behoben wird.

  • In der Praxis bedeutet dies, dass jeder PowerShell-Stream, an den Sie die Ausgabe senden, von einem externen Anrufer als Standardausgabe angesehen wird:

    • Wenn Sie beispielsweise Folgendes ausführen cmd.exe, wird keine Ausgabe angezeigt, da die Standardumleitung NULfür alle PowerShell-Streams gleichermaßen gilt:

      • C:\>powershell -noprofile -command "Write-Error error!" >NUL
    • Allerdings - neugierig - wenn Sie stderr umleiten , Powershell hat seinen Fehlerstrom stderr senden , so dass mit 2>Ihnen kann die Fehlerstrom - Ausgang erfassen selektiv; Die folgenden Ausgaben werden nur 'hi'ausgegeben - die Erfolgsstromausgabe - während die Fehlerstromausgabe in einer Datei erfasst wird err.txt:

      • C:\>powershell -noprofile -command "'hi'; Write-Error error!" 2>err.txt

Das wünschenswerte Verhalten ist:

  • Senden Sie den erfolgreichen Ausgabestream (Nummer 1) von PowerShell an stdout .
  • Senden Sie die Ausgabe aller anderen Streams an stderr. Dies ist die einzige Option, da zwischen den Prozessen nur 2 Ausgabestreams vorhanden sind - stdout (Standardausgabe) für Daten und stderr (Standardfehler) für Fehlermeldungen und alle anderen Arten von Nachrichten als Statusinformationen - das sind keine Daten .

  • Es ist ratsam, diese Unterscheidung in Ihrem Code vorzunehmen, auch wenn sie derzeit nicht eingehalten wird .


In PowerShell :

  • Write-Hostdient zur Anzeige der Ausgabe und umgeht den Erfolgsausgabestream. Daher kann die Ausgabe weder (direkt) in einer Variablen erfasst noch unterdrückt oder umgeleitet werden.

    • Die ursprüngliche Absicht bestand lediglich darin, Benutzerfeedback und einfache, konsolenbasierte Benutzeroberflächen (farbige Ausgabe) zu erstellen.

    • Aufgrund der vor Unfähigkeit erfaßt oder umgeleitet, Powershell , Version 5 vorgenommen werden , Write-Hostum den neu eingeführten Informationsstrom (Anzahl 6), so seitdem es ist möglich zu erfassen und Umleitung Write-Hostausgegeben.

  • Write-Errorist zum Schreiben von nicht terminierenden Fehlern in den Fehlerstrom (Nummer 2) gedacht ; Konzeptionell entspricht der Fehlerstrom stderr.

  • Write-Outputschreibt in den Erfolg [Ausgabe] Stream (Nummer 1), der konzeptionell stdout entspricht; Es ist der Stream, in den Daten (Ergebnisse) geschrieben werden.

    • Allerdings explizite Verwendung Write-Outputwird selten benötigt aufgrund Powershell impliziten Ausgabe Merkmal :
      • Die Ausgabe von Befehlen oder Ausdrücken, die nicht explizit erfasst, unterdrückt oder umgeleitet werden, wird automatisch an den Erfolgsstrom gesendet . zB Write-Output "Honey, I'm $HOME"und "Honey, I'm $HOME"sind gleichwertig, wobei letztere nicht nur prägnanter, sondern auch schneller sind.
mklement0
quelle