2010-05-25 10 views
5

Durante la chiamata a .NET [Console]::ReadLine() viene rilevata una perdita di dati irreversibile per leggere l'input con pipe su PowerShell.exe. In CMD, eseguire:Il testo inviato a PowerShell.exe non viene ricevuto quando si utilizza [Console] :: ReadLine()

 
>ping localhost | powershell -NonInteractive -NoProfile -C "do {$line = [Console]::ReadLine(); ('' + (Get-Date -f 'HH:mm 
:ss') + $line) | Write-Host; } while ($line -ne $null)" 
23:56:45time<1ms 
23:56:45 
23:56:46time<1ms 
23:56:46 
23:56:47time<1ms 
23:56:47 
23:56:47 

Normalmente 'ping localhost' dal Vista64 si presenta così, quindi c'è un sacco di dati mancanti dal uscita di cui sopra:

 

Pinging WORLNTEC02.bnysecurities.corp.local [::1] from ::1 with 32 bytes of data: 
Reply from ::1: time<1ms 
Reply from ::1: time<1ms 
Reply from ::1: time<1ms 
Reply from ::1: time<1ms 

Ping statistics for ::1: 
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss), 
Approximate round trip times in milli-seconds: 
    Minimum = 0ms, Maximum = 0ms, Average = 0ms 

ma usando la stessa API da C# riceve tutti i dati inviati al processo (escluse alcune differenze di nuova riga). Codice:

namespace ConOutTime { 
    class Program { 
     static void Main (string[] args) { 
      string s; 
      while ((s = Console.ReadLine()) != null) { 
       if (s.Length > 0) // don't write time for empty lines 
        Console.WriteLine("{0:HH:mm:ss} {1}", DateTime.Now, s); 
      } 
     } 
    } 
} 

uscita:

 
00:44:30 Pinging WORLNTEC02.bnysecurities.corp.local [::1] from ::1 with 32 bytes of data: 
00:44:30 Reply from ::1: time<1ms 
00:44:31 Reply from ::1: time<1ms 
00:44:32 Reply from ::1: time<1ms 
00:44:33 Reply from ::1: time<1ms 
00:44:33 Ping statistics for ::1: 
00:44:33  Packets: Sent = 4, Received = 4, Lost = 0 (0% loss), 
00:44:33 Approximate round trip times in milli-seconds: 
00:44:33  Minimum = 0ms, Maximum = 0ms, Average = 0ms 

Quindi, se chiamate la stessa API da PowerShell invece di C# molte parti del StdIn get 'mangiato'. L'host PowerShell sta leggendo una stringa da StdIn anche se non ho usato "PowerShell.exe -Command -"?

+0

ho ottenuto un errore: "Un'espressione era attesa dopo '('". Se corro questo sotto PowerShell. Correggere la tua domanda per specificare CMD. Le tue domande sono piene di dettagli (grazie!) ma non potresti avere un po 'di cose semplificate rimuovendo il bit 'Get-Date'? –

+0

Confermo che i risultati sono intermittenti/inaffidabili: sembra essere basato sulla velocità, se 'ping' viene sostituito con qualcosa di più veloce (' tipo foo.txt'), non ottengo output.Se io uso qualcosa di lento ('copia con') ottengo tutto –

+0

@JayBazuzi Il timestamp per linea è stato l'unico motivo per cui ho dovuto eseguire il piping attraverso PowerShell in primo luogo. ;) – yzorg

risposta

5

È possibile utilizzare l'enumeratore $input in PowerShell per accedere ai dati inviati nel programma. Ho anche scoperto che lo [Console]::ReadLine() in qualche modo fa poco o niente. Motivi sconosciuti, però.

C:\Users\Me> ping localhost | powershell -noninteractive -noprofile -c "$input|%{(date -f HH:mm:ss)+' '+$_}" 

07:31:54 
07:31:54 Pinging Sigmund [::1] with 32 bytes of data: 
07:31:54 Reply from ::1: time<1ms 
07:31:54 Reply from ::1: time<1ms 
07:31:54 Reply from ::1: time<1ms 
07:31:55 Reply from ::1: time<1ms 
07:31:55 
07:31:55 Ping statistics for ::1: 
07:31:55  Packets: Sent = 4, Received = 4, Lost = 0 (0% loss), 
07:31:55 Approximate round trip times in milli-seconds: 
07:31:55  Minimum = 0ms, Maximum = 0ms, Average = 0ms 

C:\Users\Me>ping localhost 

Pinging Sigmund [::1] with 32 bytes of data: 
Reply from ::1: time<1ms 
Reply from ::1: time<1ms 
Reply from ::1: time<1ms 
Reply from ::1: time<1ms 

Ping statistics for ::1: 
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss), 
Approximate round trip times in milli-seconds: 
    Minimum = 0ms, Maximum = 0ms, Average = 0ms 
+0

buon trucco con $ input. Non sapevo che è possibile utilizzarlo in questo modo quando "la pipeline è al di fuori del processo di PowerShell". – stej

+0

@stej: non conosco altro modo affidabile. Ed è orribile per il golfing del codice poiché puoi ottenere solo una serie di linee di input con '@ ($ input)' ma non puoi leggere in linea quando necessario :-( – Joey

+0

@Joey questo non funziona con la conversione esadecimale, ad esempio ''{0: x}' -f $ input'. Puoi aggiornare? –

1

Una possibile soluzione è questa:

powershell -NonInteractive -NoProfile -C "ping localhost | % { ('' + (Get-Date -f 'HH:mm:ss') + $_) | Write-Host; }" 

Sto aggiungendo che per gli altri visitatori di domanda, perché penso che tu avessi alcuni motivi per cui non si usa che :)

0

Sto inoltrando la mia soluzione finale, anche se non era davvero una risposta alla mia domanda iniziale. Stavo cercando di convogliare i dati in PowerShell da un ambiente cmd.exe che aveva un sacco di strumenti specializzati (vedi www.streambase.com). Alla fine ho aggiunto gli strumenti nel mio ambiente PowerShell.

ho finito per chiamare il tool esterno dall'interno di PowerShell e tubazioni per Out-Tempo funzione avanzata ...

function Out-Time { 
param (
    [parameter(ValueFromPipeline=$true)] 
    $Value, 
    [switch] $OutputEmptyLines=$false) 
process { 
    if (!$OutputEmptyLines -and ($Value -eq $null -or $Value -eq '')) { 
    } 
    else { 
     "{0} {1}" -f @((get-date -Format "HH:mm:ss.ff"), $Value) 
    } 
} 
} 
#test 
#ping localhost | Out-Time; ping localhost | Out-Time -OutputEmpty 
Problemi correlati