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
.
我有以下 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
.