yzorg yzorg - 4 months ago 22
Powershell Question

Text piped to PowerShell.exe isn't received when using [Console]::ReadLine()

I'm getting itermittent data loss when calling .NET

[Console]::ReadLine()
to read piped input to PowerShell.exe. In CMD, run:


>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


Normally 'ping localhost' from Vista64 looks like this, so there is a lot of data missing from the output above:



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


But using the same API from C# receives all the data sent to the process (excluding some newline differences). Code:

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


Output:


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


So, if calling the same API from PowerShell instead of C# many parts of StdIn get 'eaten'. Is the PowerShell host reading string from StdIn even though I didn't use 'PowerShell.exe -Command -'?

Answer

You can use the $input enumerator in PowerShell to get access to data piped into the program. I also have found that [Console]::ReadLine() somehow does little to nothing. Unknown reasons for that, though.

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
Comments