在调用.NET [Console]::ReadLine()
读取管道输入到PowerShell.exe时,我遇到了数据丢失的问题。在CMD中,运行:
>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
通常来自Vista64的'ping localhost'看起来像这样,所以上面的输出中缺少很多数据:
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
但是使用C#中的相同API会收到发送到进程的所有数据(不包括某些换行符)。代码:
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);
}
}
}
}
输出:
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
因此,如果从PowerShell调用相同的API而不是C#,StdIn的许多部分都会被“吃掉”。 PowerShell主机是否从StdIn读取字符串,即使我没有使用'PowerShell.exe -Command - '?
答案 0 :(得分:5)
您可以使用PowerShell中的$input
枚举器来访问传输到程序中的数据。我也发现[Console]::ReadLine()
在某种程度上做得很少甚至没有。但不明原因。
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
答案 1 :(得分:1)
一个可能的解决方案是:
powershell -NonInteractive -NoProfile -C "ping localhost | % { ('' + (Get-Date -f 'HH:mm:ss') + $_) | Write-Host; }"
我正在为其他问题访问者添加它,因为我认为你有一些理由不使用它:)
答案 2 :(得分:0)
我正在提交我的最终解决方案,即使这不是我最初问题的答案。我试图从拥有大量专用工具的cmd.exe环境中将数据传输到powershell(请参阅www.streambase.com)。最后,我将这些工具添加到我的PowerShell环境中。
我最终在PowerShell中调用了外部工具,并且管道输出到Out-Time高级功能......
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