1

我有以下 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上。据我了解,当您提供 switch 参数时,其值为 true。否则是假的。但是,它似乎不起作用。看我的测试。

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:\>

谁能帮忙解释一下吗?

4

2 回答 2

1

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

更新:

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

于 2020-02-22T15:23:36.533 回答
1

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

{Write-Host "f"}

通过使用Write-Host,您将绕过PowerShell 的成功输出流(分配给变量的$temp集合)并直接打印到主机[1](控制台),因此您的输出始终会打印。

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

# "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现在写入一个新流,即信息流 (number 6),默认情况下会打印到主机。见about_Redirection。因此,6>重定向现在确实允许您捕获Write-Host输出;例如:$temp = Write-Host hi 6>&1。请注意,以这种方式捕获的对象的类型是System.Management.Automation.InformationRecord.

于 2020-02-22T15:23:45.293 回答