2010-05-25 11 views
5

Obtengo pérdida de datos intermitente cuando llamo a .NET [Console]::ReadLine() para leer la entrada canalizada a PowerShell.exe. En CMD, ejecute:El texto enviado a PowerShell.exe no se recibe cuando se usa [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' de Vista64 se parece a esto, así que hay una gran cantidad de datos que faltan en la salida anterior:

 

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 

pero utilizando la misma API de C# recibe todos los datos enviados al proceso (excluyendo algunas diferencias de línea nueva). Código:

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); 
      } 
     } 
    } 
} 

Salida:

 
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 

lo tanto, si llamar a la misma API de PowerShell en lugar de C# muchas partes del StdIn conseguir 'comido'. ¿El host de PowerShell lee la cadena de StdIn aunque no utilicé 'PowerShell.exe -Command -'?

+0

que tiene un error: "Se esperaba una expresión después '('." Si funciono esto bajo PowerShell. Repasando su pregunta para especificar CMD. Sus preguntas están llenas de buenos detalles (¡gracias!) pero ¿no podría haber simplificado un poco las cosas al eliminar el bit 'Get-Date'? –

+0

Confirmo que los resultados son intermitentes/poco fiables. Parece estar basado en la velocidad. Si 'ping' se reemplaza con algo más rápido (' type foo.txt'), no obtengo salida. Si uso algo lento ('copy con') obtengo todo –

+0

@JayBazuzi La marca de tiempo por línea fue la única razón por la que estaba pasando por PowerShell en primer lugar. ;) – yzorg

Respuesta

5

Puede usar el enumerador $input en PowerShell para obtener acceso a los datos introducidos en el programa. También he encontrado que [Console]::ReadLine() de alguna manera hace poco o nada. Sin embargo, razones desconocidas para eso.

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

buen truco con $ entrada. No sabía que es posible usarlo de esta manera cuando "la tubería está fuera del proceso de Powershell". – stej

+0

@stej: No conozco otra manera confiable. Y es horrible para el golf de código ya que solo se puede obtener una serie de líneas de entrada con '@ ($ input)' pero no se puede leer en línea cuando sea necesario :-( – Joey

+0

@Joey esto no funciona con la conversión hexadecimal, por ejemplo ''{0: x}' -f $ input'. ¿Puedes actualizar? –

1

Una posible solución es la siguiente:

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

estoy añadiendo que para otros visitantes de interrogación, porque creo que tenía algunas razones por las que no usa eso :)

0

Presento mi solución final, incluso si no fue realmente una respuesta a mi pregunta inicial. Estaba tratando de canalizar datos a powershell desde un entorno cmd.exe que tenía un montón de herramientas especializadas (ver www.streambase.com). Finalmente, agregué las herramientas en mi entorno powershell.

que terminó llamando a la herramienta externa desde dentro PowerShell y tuberías a Tiempo de salida de la función avanzada ...

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 
Cuestiones relacionadas