简体   繁体   English

PowerShell 开关参数没有按预期工作

[英]PowerShell switch parameter doesn't work as expected

I have the following PowerShell function to help me do benchmarks.我有以下 PowerShell function 来帮助我做基准测试。 The idea is that you provide the command and a number and the function will run the code that number of times.这个想法是您提供命令和一个数字,function 将运行该代码的次数。 After that the function will report the testing result, such as Min, Max and Average time taken.之后 function 将报告测试结果,例如所用的最小、最大和平均时间。

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

The problem is with the switch parameter $ShowOutput .问题出在switch参数$ShowOutput As I understand, when you provide a switch parameter, its value is true.据我了解,当您提供开关参数时,它的值为真。 Otherwise it's false.否则就是假的。 However it doesn't seem to work.但是它似乎不起作用。 See my testing.看我的测试。

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

Can anyone help to explain it please?谁能帮忙解释一下?

This is because Write-Host doesn't return the object and is not a part of pipeline stream, instead it sends text directly to console.这是因为Write-Host不返回 object 并且不是管道 stream 的一部分,而是直接将文本发送到控制台。 You can't simply hide Write-Host output by writing it to variable, because Write-Host writes to console stream which isn't exposed in PowerShell before version 5. What you need is to replace Write-Host with Write-Output cmdlet call.您不能简单地通过将Write-Host output 写入变量来隐藏它,因为Write-Host写入控制台 stream,在版本 5 之前的 PowerShell 中未公开。您需要的是用Write-Output cmdlet 调用替换Write-Host . Then you get what you expect.然后你得到你所期望的。 This solution is valid for PowerShell 2.0+.此解决方案适用于 PowerShell 2.0+。

Update:更新:

Starting with PowerShell 5, Write-Host writes to its dedicated stream and you can handle and redirect this stream somewhere else.从 PowerShell 5 开始, Write-Host写入其专用的 stream,您可以处理并将此 stream 重定向到其他地方。 See this response for more details: https://stackoverflow.com/a/60353648/3997611 .有关详细信息,请参阅此回复: https://stackoverflow.com/a/60353648/3997611

The problem is with the specific script block you're passing, not with your [switch] parameter declaration (which works fine):问题在于您传递的特定脚本块,而不是您的[switch]参数声明(工作正常):

{Write-Host "f"}

By using Write-Host , you're bypassing PowerShell's success output stream (which the assignment to variable $temp collects) and printing directly to the host [1] (the console), so your output always prints.通过使用Write-Host ,您将绕过PowerShell 的成功 output stream(分配给变量$temp收集)并直接打印到主机[1] (控制台),因此您的 output始终打印。

To print to the success output stream, use Write-Output , or better yet, use PowerShell's implicit output feature:要打印成功 output stream,请使用Write-Output ,或者更好的是,使用 PowerShell 的隐式output 功能:

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

[1] In PowerShell 5.0 and higher, Write-Host now writes to a new stream, the information stream (number 6 ), which by default prints to the host. [1] 在 PowerShell 5.0 及更高版本中, Write-Host现在写入一个新的 stream,信息 stream(数字6 ),默认打印到主机。 See about_Redirection .请参阅about_Redirection Therefore, a 6> redirection now does allow you to capture Write-Host output;因此, 6>重定向现在允许您捕获Write-Host output eg: $temp = Write-Host hi 6>&1 .例如: $temp = Write-Host hi 6>&1 Note that the type of the objects captured this way is System.Management.Automation.InformationRecord .请注意,以这种方式捕获的对象的类型是System.Management.Automation.InformationRecord

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM