Powershell管道外部命令的不同行为

时间:2019-06-11 16:17:13

标签: powershell powershell-5.0 iisreset

我试图为外部命令输出的所有行添加时间戳。下面是我的代码:

function Out-Information
{
    [CmdletBinding()]
    param
    (
        [Parameter(ValueFromPipeline=$true)]
        [String]$String
    )

    process
    {
        $datetime = (Get-Date).ToString('yyyy-MM-dd HH:mm:ss.fff', [System.Globalization.CultureInfo]::InvariantCulture)
        Write-Information "[$datetime] $String"
    }
}

$InformationPreference = 'Continue'
& ping 8.8.8.8 | Out-Information

使用ping命令可以正常工作。输出:

[2019-06-11 12:05:47.728] 
[2019-06-11 12:05:47.729] Pinging 8.8.8.8 with 32 bytes of data:
[2019-06-11 12:05:51.697] Request timed out.
[2019-06-11 12:05:56.704] Request timed out.
[2019-06-11 12:06:01.698] Request timed out.
[2019-06-11 12:06:06.702] Request timed out.
[2019-06-11 12:06:06.702] 
[2019-06-11 12:06:06.702] Ping statistics for 8.8.8.8:
[2019-06-11 12:06:06.702]     Packets: Sent = 4, Received = 0, Lost = 4 (100% loss),

线条完全延迟5秒显示,正如我们在控制台窗口中运行时所看到的。

但是当我尝试运行iisreset命令时,所有行一次出现:

(Get-Date).ToString('yyyy-MM-dd HH:mm:ss.fff', [System.Globalization.CultureInfo]::InvariantCulture)
& iisreset /restart | Out-Information

输出:

2019-06-11 12:12:30.812
[2019-06-11 12:12:56.214] 
[2019-06-11 12:12:56.214] Attempting stop...
[2019-06-11 12:12:56.214] 
[2019-06-11 12:12:56.214] Internet services successfully stopped
[2019-06-11 12:12:56.214] 
[2019-06-11 12:12:56.214] Attempting start...
[2019-06-11 12:12:56.214] 
[2019-06-11 12:12:56.214] Internet services successfully restarted
[2019-06-11 12:12:56.214] 

但是当我直接从控制台运行iisreset时,我看到输出是一行一行的。

为什么行为不同?在一般情况下,如何捕获正确的时间戳?

1 个答案:

答案 0 :(得分:1)

考虑这两个过程如何起作用:

您的第一个示例@ParseClassName("Lesson")提供了“活动输出”,这意味着该输出是实时发生的,您和您的脚本在前进时都可以看到。

ping仅在命令完成后才输出,因此时间戳表示为同时返回所有这些值。虽然时间戳不一定准确,但这是应用程序的行为。

iisresetiisreset开关一起运行时,实际上会产生一个新线程来分别执行/restart/stop命令。所有这些都返回到原始/start线程,然后该线程将所有iisreset /restart/stop的输出显示为一个结果,而不是全部显示在同一时间戳上。