Powershell:异步管道

姜茶

我需要使用从第一个功能到第二个功能的输出。第一个函数的输出将一点一点地生成,但是我希望第二个函数在可用时立即使用它。你能帮忙吗?我使用sleep 5来演示延迟。下面是代码。

Function Test-Service {

  $p = Get-Service | select name, CanStop
  foreach($m in $p)
  {
    $instance = New-Object PSObject -Property @{
    Name = $m.name
    CanStop = $m.CanStop
    }
    write-host $instance
    sleep 5
  }

}

Function Get-Something {
    [CmdletBinding()]
        Param(
            [Parameter(ValueFromPipelineByPropertyName)]
                $instance
        )
        process {
            $name = $instance.name
            $canstop = $instance.canstop
            Write-Host "You passed the parameter $Name $CanStop into the function"
        }
}

输出如下:

@ {Name = AarSvc_f5f1f38; CanStop = True} @ {Name = Adob​​eARMservice; CanStop = True} ...这是第一个函数“ Test-Service”的输出。似乎它甚至没有被Get-Something接收

谢谢

更新#1:检查@ mklement0和@ zett42的反馈后,我意识到我误解了Write-Host与pipleline。

然后,我尝试如下所示的新示例(这是我的更多真实代码),根据$ list在当前目录下创建了许多空的.tbd文件。然后,我阅读列表,获取x和y的位置,并将名称x,y传递给下一个使用的函数,我运行它们的方式是:

Populate-NextIcon -List $instance| Launch-Test

我希望能定期看到屏幕上的输出,但是根本没有输出。这意味着我的“启动测试”功能未正确调用。

function Launch-TEST
{
    
    [CmdletBinding()]
    Param(
            [Parameter(ValueFromPipelineByPropertyName )]
                [String]$name,
            [Parameter(ValueFromPipelineByPropertyName )]
                [int]$x,
            [Parameter(ValueFromPipelineByPropertyName )]
                [int]$y              
        )
    
    $prefix = "Launch-"
    $message = "${prefix}: Received ${name}"
    write-host $message
}   
function Populate-NextIcon
{
    param ([System.Collections.ArrayList]$list)
    while($true)
    {
        $icons = Get-ChildItem -path .\*.tbd | Sort-Object LastWriteTime
        if($icons.count -eq 0)
        {
            break
        }
        $t = Get-Date -Format "yyyy_MM_dd_HHmmss"
        $icon = $icons[0]
        $baseName = $icon.BaseName
        Add-Content -Path $icon.FullName -Value $t 
        $i = $list | where-object {$_.name -eq $baseName}
        [PSCustomObject]@{
        Name = $i.name
        x = $i.x
        y = $i.y
        }
        
        $sleep = (Get-Content -Path $icon.FullName | Measure-Object -Line).Lines
        $sleep = $sleep * 5
        sleep $sleep    

    }
    
}

如果我以Populate-NextIcon的身份运行它-List $ list

我将得到低于预期的输出:

Name            x   y
----            -   -
AAA_PROD    1300 358
BBB_PROD 2068 250
CCC_PROD    1556 358

但是,如果我以管道方式将其作为Populate-NextIcon -List $ instance | 发射测试

然后,尽管我可以看到这些.tbd文件已更新,但屏幕上没有任何输出。似乎第一个函数的输出保存在某个地方?

zett42

如评论中所述,使用Write-Host不会产生可以直接在管道中进一步处理的输出。顾名思义,Write-Host写入主机(又名信息流),但是我们需要写入输出(又名成功)流。

更惯用的方式是:

Function Test-Service {

  $p = Get-Service | select name, CanStop
  foreach($m in $p)
  {
    [PSCustomObject]@{
        Name = $m.name
        CanStop = $m.CanStop
    }
    sleep 5
  }
}

通过创建一个[PSCustomObject]没有将其分配给变量的变量,它将自动作为函数的输出结束。这类似于New-Object PSObject -Property ...但不那么冗长。


我在第一句话中写道:“Write-Host不会产生可以直接处理的输出”。直接强调是因为可以使您的原始代码像这样工作:

Test-Service 6>&1 | Get-Something

这里的数字6代表信息流(Write-Host输出到),而数字1代表成功流。因此,我们将信息流重定向到成功流,该成功流实际上将两个流合并为一个。现在,该函数的输出可以成功传递到Get-Something

关于重定向


附带说明一下,这个问题的标题有些令人困惑,因为在常规管道处理中没有异步的东西。当管道中的每个cmdlet处理其输入时,管道的其他部分均未运行,并且脚本的其余部分仅在管道处理完成之后才继续。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章