PowerShell:有没有办法获取通过管道传输到函数中的对象总数?

标签 powershell scripting pipeline

编辑:添加说明,我的愿望只是显示一个进度条,其已知结束(例如管道结束),以便函数可以提供完成百分比(通常用于大型集数百或数千)。我偶尔会编写函数来从两个管道或通过参数获取对象,这样函数就可以很灵活。

来自参数的对象数组的进度条非常简单,相当于先拉入完整的管道集,然后再次处理它们。我一直在避免后者,我只是放弃了这种情况下的写入进度,因为它不值得影响。

我不记得在哪里看到它,但有人提到 $PSCmdlet.MyInvocation 可能会提供计数,但也许我对此的解释不正确。


我编写了一些采用管道输入的函数,并且经常想为通过管道进入函数的所有对象编写一个百分比进度条。

有没有办法在函数的开头获取总计数?

我知道当函数循环遍历管道对象时如何增加计数器,但这只会让我得到到目前为止处理的对象数量。我想通过根据完整管道计数计算它来获得其中的百分比。

我查看了 $MyInvocation$PSCmdlet.MyInvocation 属性,但无论管道集有多大,PipelineLength 和 PipelinePosition 值区域始终为“2”是。

注意:这不是我关注的解决方案,它只是我发现看起来很有希望的事情之一

这是一个测试:

Function Test-Pipeline {
[CmdletBinding()]

PARAM(
    [Parameter(ValueFromPipeLine=$true,ValueFromPipelineByPropertyName=$true)]
    [Alias("FullName")]
    [psobject[]]$Path
)

BEGIN{
    $PSCmdlet.MyInvocation | Select *
}
PROCESS{
    ForEach ($xpath in $Path) {
        $filepath = Resolve-Path $xpath | Select -ExpandProperty Path
    }
}
END{}
}

当我输入 dir 的内容时(该文件夹包含 20 个项目),我得到:

PS C:\Temp> Dir | Test-Pipeline

MyCommand             : Test-Pipeline
BoundParameters       : {}
UnboundArguments      : {}
ScriptLineNumber      : 1
OffsetInLine          : 7
HistoryId             : 213
ScriptName            : 
Line                  : Dir | Test-Pipeline
PositionMessage       : At line:1 char:7
                        + Dir | Test-Pipeline
                        +       ~~~~~~~~~~~~~
PSScriptRoot          : 
PSCommandPath         : 
InvocationName        : Test-Pipeline
PipelineLength        : 2
PipelinePosition      : 2
ExpectingInput        : True
CommandOrigin         : Runspace
DisplayScriptPosition : 

最佳答案

如前所述,如果您想知道您将在 cmdlet 中接收的对象数量以预定义进度条的单位您基本上不能(在不中断流处理的情况下)。
任何看起来做你想做的“解决方案”,实际上通过收集所有对象(在内存中),计算它们并最终一次释放它们来阻塞整个管道。 这将违反 Strongly Encouraged Development GuidelinesWrite Single Records to the Pipeline并导致高内存使用率。

解释

可视化装配线,您负责为经过您的站点的所有对象着色。现在您想知道今天需要处理多少对象。 除非您站外的某个人 (cmdlet) 告诉您有多少人会跟随,您只能通过接收所有计算它们的对象来确定, (仍然着色它们)并传递它们。由于所有这些操作都需要时间(以及元素的储藏室),下一站的人会不高兴,因为他将一次性收到所有元素,而且比预期的要晚很多...

技术上

让我们构建一个从 ProcessList 生成无色对象的 cmdlet:

function Create-Object {
    [CmdletBinding()]
    param(
        [Parameter(ValueFromPipeLine=$true)]$ProcessList,
        [Switch]$Show
    )
    begin {
        $Index = 0
    }
    process {
        $Object = [PSCustomObject]@{
            Index = $Index++
            Item  = $ProcessList
            Color = 'Colorless'
        }
        if ($Show) { Write-Host 'Created:' $Object.PSObject.Properties.Value }
        $Object
    }
}

这就是你,为对象着色:

function Color-Object {
    [CmdletBinding()]
    param(
        [Parameter(ValueFromPipeLine=$true)]$InputObject,
        [Switch]$Show
    )
    process {
        $InputObject.Color = [ConsoleColor](Get-Random 16)
        if ($Show) { Write-Host 'Colored:' $InputObject.PSObject.Properties.Value }
        $InputObject
    }
}

这将是结果:

'a'..'e' |Create-Object |Color-Object

Index Item       Color
----- ----       -----
    0    a DarkMagenta
    1    b      Yellow
    2    c        Blue
    3    d        Gray
    4    e       Green

现在让我们看看实际是如何处理的:

'a'..'e' |Create-Object -Show |Color-Object -Show

Created: 0 a Colorless
Colored: 0 a DarkGreen

Created: 1 b Colorless
Colored: 1 b DarkRed
Created: 2 c Colorless
Colored: 2 c Gray
Created: 3 d Colorless
Colored: 3 d DarkGreen
Created: 4 e Colorless
Colored: 4 e DarkGray
Index Item     Color
----- ----     -----
    0    a DarkGreen
    1    b   DarkRed
    2    c      Gray
    3    d DarkGreen
    4    e  DarkGray

如您所见,第一项“a”(索引 0)是彩色 第二个项目“b”(索引1)之前创建!
换句话说,Create-Object 尚未创建所有对象,也无法知道接下来会创建多少对象。除了像前面解释的那样只是等待你不想做的事情,如果有很多对象当然想避免,对象很胖(PowerShell 对象通常很胖)或者在输入缓慢的情况下(另请参阅:Advocating native PowerShell)。这意味着如果枚举(计数)对象对于过程的其余部分来说是微不足道的,那么您可能希望对此进行异常(exception)处理:例如收集文件信息 (Get-ChildItem) 以稍后调用繁重的进程(例如 Get-FileHash)。

关于PowerShell:有没有办法获取通过管道传输到函数中的对象总数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67529017/

相关文章:

powershell - Jmeter:如何从命令行禁用特定线程组

Linux shell 脚本 : How to store output from terminal in integers (but only numbers)?

python - 带有 OHE 的 ColumnTransformer 和 Pipeline - 执行 ct 后 OHE 编码字段是保留还是删除?

powershell - 将字符串转换为 PSCustomObject

function - 如何将参数传递给变量引用的函数

powershell - 管道进入 ScriptBlock

security - 以编程方式获取 SSRS 2008 中的用户角色和权限

python - 如何将 bugzilla 的 webservice xml-rpc 与 python 一起使用?

redis - 将管道与 redis-cluster 一起使用时出现 Predis 错误

azure - 处理 Azure 数据工厂中的多个目标 - 数据流管道