首页 > 解决方案 > 从自定义参数完成器/动态参数访问当前管道项

问题描述

我正在玩弄 cmdlet 的自定义参数完成器。为了学习如何编写它们,我制作了一个示例 cmdlet,其中一个是可取的;cmdlet 调用给定对象的方法,因此您需要发现它们可用的方法。当我最初开始时,我想因为内置 cmdletSelect-Object很容易为自动完成提供对象属性名称,所以它很容易复制,但要使用方法名称。但是,自定义 cmdlet 似乎无法访问管道内容,所以我的想法落空了。

我觉得自然而然的另一件事是动态ValidateSet地将输入限制为有效方法。长话短说,它也遇到了同样的问题。

这是我迄今为止尝试过的完整代码:

function Invoke-ObjectMethod {
    [CmdletBinding()]
    param(
        # Method to call.
        [Alias('Name', 'MethodName')]
        # [ArgumentCompleter({
        #       [OutputType([System.Management.Automation.CompletionResult])]
        #       param(
        #           [string] $CommandName,
        #           [string] $ParameterName,
        #           [string] $WordToComplete,
        #           [System.Management.Automation.Language.CommandAst] $CommandAst,
        #           [System.Collections.IDictionary] $FakeBoundParameters
        #       )
        #       $_, $PSBoundParameters | Out-String | Out-Host
        #       if(!$FakeBoundParameters.ContainsKey('InputObject') -or $ParameterName -ne 'Method') {
        #           return
        #       }
        #       $static = $FakeBoundParameters.Static
        #       $FakeBoundParameters.InputObject | Get-Member "$WordToComplete*" -MemberType Method -Static:$static | ForEach-Object {
        #           $defs = $_ | Select-Object -ExpandProperty Definition | ForEach-Object { $_ -split '), ', 0, 'SimpleMatch' } | Join-String -Separator ")`n"
        #           New-Object -Type System.Management.Automation.CompletionResult -ArgumentList $_.Name, $_.Name, ParameterValue, $defs
        #       }
        #   })]
        [Parameter(Position = 0, Mandatory, ValueFromPipelineByPropertyName)]
        [string]$Method,
        # Arguments to provide to the method call.
        [AllowEmptyCollection()]
        [Parameter(Position = 1, ValueFromPipelineByPropertyName)]
        [psobject[]]$ArgumentList = @(),
        # Indicates whether the call should be static.
        [Parameter(ValueFromPipelineByPropertyName)]
        [switch]$Static,
        # Input object to invoke the method on.
        [Parameter(ValueFromPipeline, Mandatory, Position = 2)]
        $InputObject
    )
    # dynamicParam {
    #   'dynamicParam', $InputObject, $_, $PSBoundParameters | Out-String | Out-Host
    #   if($null -ne $InputObject) {
    #       $attributeCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()
    #       $attributeCollection.Add([System.Management.Automation.ParameterAttribute]@{
    #               Mandatory                       = $true
    #               Position                        = 0
    #               ValueFromPipelineByPropertyName = $true
    #           })
    #       $attributeCollection.Add([System.Management.Automation.AliasAttribute]::new('Name', 'MethodName'))
    #       $attributeCollection.Add([System.Management.Automation.ValidateSetAttribute]::new(@($InputObject | Get-Member -MemberType Method -Static:$Static | Select-Object -ExpandProperty Name -Unique)))
    #       $attributeCollection | Out-Host
    #       $dynParam = [System.Management.Automation.RuntimeDefinedParameter]::new('Method', [string], $attributeCollection)
    #       $paramDictionary = [System.Management.Automation.RuntimeDefinedParameterDictionary]::new()
    #       $paramDictionary.Add('Method', $dynParam)
    #       return $paramDictionary
    #   }
    # }
    process {
        $sc = [scriptblock]::Create('$args[0]{1}($args[1])({0})' -f @(($ArgumentList | ForEach-Object {
            '$args[2][{0}]' -f ($i++)
        } | Join-String -Separator ','), ($Static ? '::' : '.')))
        $sc.Invoke($InputObject, $Method, $ArgumentList ?? @($null))
    }
}

我注释掉了功能失调的代码,使 cmdlet 进入工作状态。是否有任何技巧可以复制内置 cmdlet 的功能以进行自动完成?我目前正在使用最新版本的 Powershell Core 7.1.5。

标签: powershell-core

解决方案


推荐阅读