Параметр переключателя PowerShell не работает должным образом - PullRequest
1 голос
/ 22 февраля 2020

У меня есть следующая функция 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:\>

Может кто-нибудь помочь объяснить это, пожалуйста?

Ответы [ 2 ]

1 голос
/ 22 февраля 2020

Проблема в заданном вами блоке сценария c, а не в объявлении параметра [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 теперь записывает в новый поток информацию поток (номер 6), который по умолчанию печатает на хост. См. about_Redirection. Следовательно, перенаправление 6> теперь делает , позволяя вам захватить Write-Host вывод; например: $temp = Write-Host hi 6>&1. Обратите внимание, что тип объектов, захваченных таким образом, составляет System.Management.Automation.InformationRecord.

1 голос
/ 22 февраля 2020

Это потому, что Write-Host не возвращает объект и не является частью потока конвейера, вместо этого он отправляет текст непосредственно на консоль. Вы не можете просто скрыть вывод Write-Host, записав его в переменную, потому что Write-Host записывает в консольный поток, который не доступен в PowerShell до версии 5. Вам нужно заменить Write-Host на вызов командлета Write-Output , Тогда вы получите то, что ожидаете. Это решение действительно для PowerShell 2.0 +.

Обновление:

Начиная с PowerShell 5, Write-Host выполняет запись в свой выделенный поток, и вы можете обрабатывать и перенаправлять этот поток где-нибудь еще. Смотрите этот ответ для более подробной информации: { ссылка }.

...