0

作为此问题的补充:如何强制声明的参数需要显式命名?我正在与管道作斗争。假设我想要 this 声明的行为:

param(
   $installdir, 
   $compilemode, 
   [Parameter(Position=0, ValueFromRemainingArguments=$true)] $files
   )

也就是说,我可以这样调用我的脚本:

c:\> MyScript -installdir c:\ file-1.txt file-2.txt file-3.txt

但现在我也希望能够这样做:

c:\> gi file-*.txt |MyScript -installdir c:\

我可能会考虑为参数添加一个装饰,如下所示:

param(
   $installdir, 
   $compilemode, 
   [Parameter(
       Position=0, 
       ValueFromRemainingArguments=$true, 
       ValueFromPipeline=$true
   )] $files
   )

但实际发生的是我只在我的参数中得到 1 个参数,即我没有得到一个包含所有生成文件的数组gi,我只得到列表中的第一个。

我尝试的第二种方法是使用$input变量(而不是使用ValueFromPipeline装饰器),但是在尝试调用脚本时出现错误:

输入对象不能绑定到命令的任何参数,因为命令不接受管道输入,或者输入及其属性与接受管道输入的任何参数都不匹配。

我可以从这里去哪里?

4

1 回答 1

3

您可以在没有 ValueFromRemainingArguments 的情况下声明它:

param(
   [Parameter(
       Position=0, 
       ValueFromPipeline=$true,
       ValueFromPipelineByPropertyName=$true)]
   [Alias('PSPath')]
   [string[]]
   $files,
   $installdir, 
   $compilemode
   )

然后使用逗号运算符将多个文件作为数组传递,例如:

 MyScript -installdir c:\ file-1.txt,file-2.txt,file-3.txt

注意:为了接受来自 Get-Item 和 Get-ChildItem 等命令的输入,请使用 ValueFromPipelineByPropertyName 并添加参数别名“PSPath”,它将在 Get-Item/Get-ChildItem 输出的对象上找到 PSPath 属性。

我在 ISE 中对此进行了测试,它工作正常:

function foo
{
    param(
       [Parameter(
           Position=0, 
           ValueFromPipeline=$true,
           ValueFromPipelineByPropertyName=$true)]
       [Alias('PSPath')]
       [string[]]
       $files,
       $installdir, 
       $compilemode
       )

    process {
        foreach ($file in $files) {
            "File is $file, installdir: $installdir, compilemode: $compilemode"
        }
    }
}

foo a,b,c -installdir c:\temp -compilemode x64
ls $home -file | foo -installdir c:\bin -compilemode x86

仅供参考,这是我一直用来创建接受管道输入或数组输入以及通配符路径的命令的模板:

function Verb-PathLiteralPath
{
    [CmdletBinding(DefaultParameterSetName="Path",
                   SupportsShouldProcess=$true)]
    #[OutputType([output_type_here])] # Uncomment this line and specify the output type  of this
                                      # function to enable Intellisense for its output.
    param(
        [Parameter(Mandatory=$true, 
                   Position=0, 
                   ParameterSetName="Path", 
                   ValueFromPipeline=$true, 
                   ValueFromPipelineByPropertyName=$true,
                   HelpMessage="Path to one or more locations.")]
        [ValidateNotNullOrEmpty()]
        [SupportsWildcards()]
        [string[]]
        $Path,

        [Alias("PSPath")]
        [Parameter(Mandatory=$true, 
                   Position=0, 
                   ParameterSetName="LiteralPath", 
                   ValueFromPipelineByPropertyName=$true,
                   HelpMessage="Literal path to one or more locations.")]
        [ValidateNotNullOrEmpty()]
        [string[]]
        $LiteralPath
    )

    Begin 
    { 
        Set-StrictMode -Version Latest
    }

    Process 
    {
        if ($psCmdlet.ParameterSetName -eq "Path")
        {
            if (!(Test-Path $Path)) {
                $ex = new-object System.Management.Automation.ItemNotFoundException "Cannot find path '$Path' because it does not exist."
                $category = [System.Management.Automation.ErrorCategory]::ObjectNotFound
                $errRecord = new-object System.Management.Automation.ErrorRecord $ex, "PathNotFound", $category, $Path
                $psCmdlet.WriteError($errRecord)
            }

            # In the -Path (non-literal) case, resolve any wildcards in path
            $resolvedPaths = $Path | Resolve-Path | Convert-Path
        }
        else 
        {
            if (!(Test-Path $LiteralPath)) {
                $ex = new-object System.Management.Automation.ItemNotFoundException "Cannot find path '$LiteralPath' because it does not exist."
                $category = [System.Management.Automation.ErrorCategory]::ObjectNotFound
                $errRecord = new-object System.Management.Automation.ErrorRecord $ex, "PathNotFound", $category, $LiteralPath
                $psCmdlet.WriteError($errRecord)
            }

            # Must be -LiteralPath
            $resolvedPaths = $LiteralPath | Convert-Path
        }

        foreach ($rpath in $resolvedPaths) 
        {
            if ($pscmdlet.ShouldProcess($rpath, "Operation"))
            {
                # .. process rpath
            }
        }  
    }

    End
    {
    }
}
于 2013-09-26T22:15:10.450 回答