PowerShell 开关参数未按预期工作

PowerShell switch parameter doesn't work as expected

我有以下 PowerShell 函数来帮助我进行基准测试。这个想法是您提供命令和数字,函数将 运行 代码多次。之后该函数将报告测试结果,例如所用的最小、最大和平均时间。

function Measure-MyCommand()
{
    [CmdletBinding()]
    Param (
        [Parameter(Mandatory = $True)] [scriptblock] $ScriptBlock,
        [Parameter()] [int] $Count = 1,
        [Parameter()] [switch] $ShowOutput
    )

    $time_elapsed = @();
    while($Count -ge 1) {
        $timer = New-Object 'Diagnostics.Stopwatch';
        $timer.Start();
        $temp = & $ScriptBlock;
        if($ShowOutput) {
            Write-Output $temp;
        }
        $timer.Stop();
        $time_elapsed += $timer.Elapsed;
        $Count--;
    }

    $stats = $time_elapsed | Measure-Object -Average -Minimum -Maximum -Property Ticks;

    Write-Host "Min: $((New-Object 'System.TimeSpan' $stats.Minimum).TotalMilliseconds) ms";
    Write-Host "Max: $((New-Object 'System.TimeSpan' $stats.Maximum).TotalMilliseconds) ms";
    Write-Host "Avg: $((New-Object 'System.TimeSpan' $stats.Average).TotalMilliseconds) ms";
}

问题出在 switch 参数 $ShowOutput 上。据我了解,当您提供开关参数时,它的值为真。否则就是假的。但是它似乎不起作用。看我的测试。

PS C:\> Measure-MyCommand -ScriptBlock {Write-Host "f"} -Count 3 -ShowOutput
f
f
f
Min: 0.4935 ms
Max: 0.8392 ms
Avg: 0.6115 ms
PS C:\> Measure-MyCommand -ScriptBlock {Write-Host "f"} -Count 3
f
f
f
Min: 0.4955 ms
Max: 0.8296 ms
Avg: 0.6251 ms
PS C:\>

谁能帮忙解释一下?

这是因为 Write-Host 没有 return 对象并且不是管道流的一部分,而是直接将文本发送到控制台。您不能简单地通过将输出写入变量来隐藏 Write-Host 输出,因为 Write-Host 写入控制台流,而版本 5 之前的 PowerShell 中未公开该流。您需要的是替换 Write-Host使用 Write-Output cmdlet 调用。然后你得到你所期望的。此解决方案适用于 PowerShell 2.0+。

更新:

从 PowerShell 5 开始,Write-Host 写入其专用流,您可以在其他地方处理和重定向该流。有关详细信息,请参阅此回复:.

问题出在您传递的特定脚本块上,而不是您的 [switch] 参数声明(工作正常):

{Write-Host "f"}

通过使用 Write-Host,您可以 绕过 PowerShell 的成功输出流(分配给变量 $temp 收集)并直接打印到主机[1](控制台),所以你的输出总是打印。

要打印到成功输出流,请使用 Write-Output,或者更好的是,使用 PowerShell 的 implicit 输出功能:

# "f", due not being capture or redirected, is implicitly sent 
# to the success output stream. 
Measure-MyCommand -ScriptBlock { "f" } -Count 3 -ShowOutput

[1] 在 PowerShell 5.0 及更高版本中,Write-Host 现在写入新流,信息流(编号 6),默认情况下打印到主机.参见 about_Redirection。 因此,6> 重定向现在 确实 允许您捕获 Write-Host 输出;例如:$temp = Write-Host hi 6>&1。注意这样抓取到的对象类型是System.Management.Automation.InformationRecord.