Come produrre qualcosa in PowerShell


211

Sto eseguendo uno script PowerShell da un file batch. Lo script recupera una pagina Web e verifica se il contenuto della pagina è la stringa "OK".

Lo script di PowerShell restituisce un livello di errore allo script batch.

Lo script batch viene eseguito da ScriptFTP , un programma di automazione FTP. Se si verifica un errore, posso fare in modo che ScriptFTP invii l'intero output della console all'amministratore tramite e-mail.

Nello script di PowerShell, desidero visualizzare il valore restituito dal sito Web se non è "OK", quindi il messaggio di errore viene incluso nell'output della console e quindi nella posta di stato.

Sono nuovo di PowerShell e non sono sicuro di quale funzione di output utilizzare per questo. Posso vederne tre:

  • Write-Host
  • Write-Output
  • Write-Error

Quale sarebbe la cosa giusta da usare per scrivere sull'equivalente di Windows stdout?

Risposte:


197

La semplice presentazione di qualcosa è che PowerShell è una cosa di bellezza - e uno dei suoi maggiori punti di forza. Ad esempio, il comune Hello, World! l'applicazione è ridotta a una sola riga:

"Hello, World!"

Crea un oggetto stringa, assegna il valore di cui sopra ed essendo l'ultimo elemento sulla pipeline di comandi, chiama il .toString()metodo e restituisce il risultato STDOUT(per impostazione predefinita). Una cosa di bellezza.

Gli altri Write-*comandi sono specifici per inviare il testo ai flussi associati e hanno il loro posto in quanto tale.


9
Non è proprio quello che succede. È un'espressione letterale di stringa e l'unica cosa nella sua pipeline. Quindi è equivalente a "Hello, World!" | Out-Host. Out-Hostd'altra parte invia oggetti all'host PowerShell per la visualizzazione e la sua implementazione dipende dall'host. L'host della console li invia all'handle di output standard (passando Out-Defaultlungo il percorso), in effetti. PowerShell ISE li visualizza nel riquadro di output, tuttavia, e altri host possono fare ancora altre cose.
Joey,

5
Inoltre, gli oggetti non vengono convertiti ciecamente in stringa, ma passano attraverso un formatter che decide cosa farne. Ecco perché vedi Get-ChildIteml'output in forma di tabella, ad esempio, e risultati con molte proprietà (ad es. WMI) predefinite Format-Listinvece.
Joey,

120

Penso che in questo caso avrai bisogno di Write-Output .

Se hai una sceneggiatura simile

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

quindi, se chiamate lo script con output reindirizzato, qualcosa del genere yourscript.ps1 > out.txt, apparirà test2sullo schermo test1\ntest3\nin "out.txt".

Nota che "test3" e la riga Write-Output aggiungeranno sempre una nuova riga al tuo testo e in PowerShell non c'è modo di fermarlo (ciò echo -nè impossibile in PowerShell con i comandi nativi). Se vuoi la funzionalità (piuttosto semplice e semplice in Bash ) di echo -nallora vedi la risposta di samthebest .

Se un file batch esegue un comando PowerShell, molto probabilmente acquisirà il comando Write-Output. Ho avuto "lunghe discussioni" con gli amministratori di sistema su cosa dovrebbe essere scritto sulla console e cosa no. Ora abbiamo concordato che le uniche informazioni se lo script eseguito correttamente o morto devono essere Write-Host'edite, e tutto ciò che è l'autore dello script potrebbe essere necessario conoscere l'esecuzione (quali elementi sono stati aggiornati, quali campi sono stati impostati, eccetera) vanno per scrivere-output. In questo modo, quando si invia uno script all'amministratore di sistema, può facilmente runthescript.ps1 >someredirectedoutput.txte vedere sullo schermo, se tutto è a posto. Quindi inviare "someredirectedoutput.txt" agli sviluppatori.


9

Penso che quanto segue sia una buona mostra di Echo vs. Write-Host . Notate come test () restituisce effettivamente una matrice di ints, non un singolo int come si potrebbe facilmente far credere.

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])"

Uscita terminale di quanto sopra:

123
x of type 'Object[]' = 456 789
$x[0] = 456
$x[1] = 789

Posso guardarlo tutto il giorno ... Ma perché è $x = testsolo la stampa 123e non anche 456?
not2qubit

7

È possibile utilizzare uno di questi nel proprio scenario poiché scrivono nei flussi predefiniti (output ed errore). Se si stava eseguendo il piping dell'output su un altro commandlet, si vorrebbe utilizzare Write-Output , che alla fine terminerà in Write-Host .

Questo articolo descrive le diverse opzioni di output: PowerShell O è per Output


1
Grazie per il link Bontà, questo è complicato . Se Write-host è una sorta di endpoint o funzione di flushing, proverò ad andare con quello e riferirò indietro.
Pekka,

3
Write-Host "Found file - " + $File.FullName -ForegroundColor Magenta

Il magenta può essere uno dei valori dell'enumeratore "System.ConsoleColor" - Nero, DarkBlue, DarkGreen, DarkCyan, DarkRed, DarkMagenta, DarkYellow, Grey, DarkGray, Blue, Green, Cyan, Red, Magenta, Yellow, White.

Il + $File.FullNameè opzionale, e spettacoli come mettere una variabile nella stringa.


2

Semplicemente non è possibile ottenere PowerShell per accedere a quelle fastidiose newline. Non esistono script o cmdlet che lo fanno.

Ovviamente Write-Host è un'assurdità assoluta perché non puoi reindirizzare / pipe da esso! Devi semplicemente scrivere il tuo:

using System;

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

Per esempio

PS C:\> writetostdout finally I can write to stdout like echo -n
finally I can write to stdout like echo -nPS C:\>

Potresti farlo in PowerShell stesso. [System.Console] :: Write ("stringy") Tuttavia non sarai in grado di reindirizzarlo affatto in PowerShell.
Nicholi,

1

1

Quale sarebbe la cosa giusta da usare per scrivere sull'equivalente di Windows di stdout?

In effetti , ma molto purtroppo , sia Windows PowerShell e PowerShell Core come di v7.0, inviare tutta la loro 6 (!) In uscita flussi di stdout quando chiamato dall'esterno , via di PowerShell CLI .

  • Vedi questo problema di GitHub per una discussione di questo comportamento problematico, che probabilmente non verrà risolto per motivi di compatibilità con le versioni precedenti.

  • In pratica, ciò significa che qualunque flusso PowerShell a cui invii l'output verrà visto come output stdout da un chiamante esterno:

    • Ad esempio, se si esegue quanto segue da cmd.exe, non verrà visualizzato alcun output, poiché il reindirizzamento stdout si NULapplica ugualmente a tutti i flussi di PowerShell:

      • C:\>powershell -noprofile -command "Write-Error error!" >NUL
    • Tuttavia - curiosamente - se si reindirizza stderr , PowerShell fa inviare il suo flusso di errore a stderr , in modo che con 2>si può catturare l'output errore-stream in modo selettivo; solo i seguenti output 'hi'- l'output del flusso di successo - durante l'acquisizione dell'output del flusso di errori nel file err.txt:

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

Il comportamento desiderabile è:

  • Invia il flusso di output (numero 1) di successo di PowerShell a stdout .
  • Invia output da tutti gli altri flussi a stderr , che è l'unica opzione, dato che tra processi esistono solo 2 flussi di output - stdout (output standard) per i dati e stderr (errore standard) per i messaggi di errore e tutti gli altri tipi di messaggi - come come informazioni sullo stato - che non sono dati .

  • È consigliabile fare questa distinzione nel codice, anche se al momento non viene rispettato .


All'interno di PowerShell :

  • Write-Hostè per l' output di visualizzazione e ignora il flusso di output riuscito - come tale, il suo output non può essere (direttamente) catturato in una variabile né soppresso né reindirizzato.

    • Il suo intento originale era semplicemente quello di creare feedback degli utenti e creare semplici interfacce utente basate su console (output colorato).

    • A causa della precedente incapacità di essere acquisito o reindirizzato, PowerShell versione 5 ha effettuato Write-Hostil flusso di informazioni (numero 6) appena introdotto , quindi da allora è possibile acquisire e reindirizzare l' Write-Hostoutput.

  • Write-Errorè pensato per scrivere errori non terminanti nel flusso di errori (numero 2); concettualmente, il flusso di errore è l'equivalente di stderr.

  • Write-Outputscrive al flusso [numero ] di successo (numero 1), che è concettualmente equivalente a stdout; è lo stream in cui scrivere i dati (risultati).

    • Tuttavia, l'uso esplicito di Write-Outputè raramente necessario a causa della funzionalità di output implicita di PowerShell :
      • L'output di qualsiasi comando o espressione non esplicitamente acquisito, soppresso o reindirizzato viene automaticamente inviato al flusso di successo ; ad esempio, Write-Output "Honey, I'm $HOME"e "Honey, I'm $HOME"sono equivalenti, con quest'ultimo non solo più conciso, ma anche più veloce.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.