Powershell:异步管道

Powershell:异步管道,powershell,pipeline,Powershell,Pipeline,我需要使用从第一个函数到第二个函数的输出。 第一个函数的输出将一点一点地生成,但我希望第二个函数在可用时立即使用它。 你能帮忙吗?我使用sleep 5来演示延迟。 下面是代码 Function Test-Service { $p = Get-Service | select name, CanStop foreach($m in $p) { $instance = New-Object PSObject -Property @{ Name = $m.name

我需要使用从第一个函数到第二个函数的输出。 第一个函数的输出将一点一点地生成,但我希望第二个函数在可用时立即使用它。 你能帮忙吗?我使用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=AdobeARMservice;CanStop=True} ... 这是第一个函数“测试服务”的输出。似乎它甚至都没有收到的东西

谢谢

更新#1: 在检查了@mklement0和@zett42的反馈后,我意识到我误解了写主机和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    

    }
    
}

如果我把它当作 填充NextIcon-List$List

我将按预期获得以下输出:

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

但如果我把它当作 填充NextIcon-列出$instance |启动测试

然后,虽然我可以看到这些.tbd文件得到更新,但屏幕上没有输出
第一个函数的输出似乎被挂起了?

如注释中所述,使用
写主机
不会产生可以直接在管道中进一步处理的输出。正如名字所说,
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]
而不将其分配给变量,它将自动作为函数的输出。这类似于
新对象PSObject-Property…
,但不太详细


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

Test-Service 6>&1 | Get-Something
这里数字
6
代表信息流(其中
Write Host
输出到),数字
1
代表成功流。因此,我们将信息流重定向到成功流,成功流实际上将两个流合并为一个流。现在,函数的输出可以成功地传递到
获取内容



另一方面,这个问题的标题有点混乱,因为在正常的管道处理中没有异步。虽然管道中的每个cmdlet都在处理其输入,但管道中没有其他部分正在运行,脚本的其余部分只有在管道处理完成后才能继续。

如注释中所述,使用
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]
而不将其分配给变量,它将自动作为函数的输出。这类似于
新对象PSObject-Property…
,但不太详细


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

Test-Service 6>&1 | Get-Something
这里数字
6
代表信息流(其中
Write Host
输出到),数字
1
代表成功流。因此,我们将信息流重定向到成功流,成功流实际上将两个流合并为一个流。现在,函数的输出可以成功地传递到
获取内容



另一方面,这个问题的标题有点混乱,因为在正常的管道处理中没有异步。当管道中的每个cmdlet处理其输入时,管道中没有其他部分正在运行,脚本的其余部分只有在管道处理完成后才能继续。

Write Host
不会写入成功流。您需要使用
写入输出
写入主机
不会写入成功流。你需要使用
写输出
。有趣的是,如果我使用这个例子,它是有效的,但是如果我使用其他东西,它就不会让人感到困惑。我将其命名为“Async”,因为我希望生产者创建一个对象,然后消费者在不等待生产者完成所有对象的情况下使用它。这是我在测试服务中看到的模式/在根据反馈进行更改后获得一些东西。然而,在我的新示例中,它不起作用。这是因为while和foreach的不同吗?@Ginger\u Chacha是的,但它仍然不是异步的,因为生产者必须等待单个输出项通过管道链处理。我看不到您更新的代码中有错误。也许是测试错误?尝试在调试器中单步执行代码,以查看是否一切正常。感谢@zett42的评论。我还有很长的路要走:)谢谢你的意见。我已经使用foreach对象循环暂时解决了我的问题,但是后来出现了一些新的东西……有趣的是——如果我使用这个例子,它是有效的,但是如果我使用了其他东西,它就不会令人困惑了。我将其命名为“Async”,因为我希望生产者创建一个对象,然后消费者在不等待生产者完成所有对象的情况下使用它。这是我在测试服务中看到的模式/在根据反馈进行更改后获得一些东西。然而在我的新例子中