具有不同参数的动态调用命令

时间:2015-12-09 10:24:20

标签: powershell

在PowerShell脚本中,我想要读取包含以下内容的CSV文件:

Type  Title      Param1        Param2       
----  -----      ------        ------       
Type1 Foo type 1 ValueForType1              
Type2 Foo type 2               ValueForType2

当type为Type1时,我必须调用名为New-FooType1的函数,当type为Type2时,函数名为New-FooType2,依此类推:

function New-FooType1{
    param(
        [Parameter(Mandatory=$true, ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$Title,
        [Parameter(Mandatory=$true, ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$Param1
    )

    Write-Host "New-FooType1 $Title with $Param1"
}

function New-FooType2{
    param(
        [Parameter(Mandatory=$true, ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$Title,
        [Parameter(Mandatory=$true, ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$Param2
    )

    Write-Host "New-FooType2 $Title with $Param2"
}

我正在尝试使用动态调用路由对任一函数的调用:

$csv | % {
    $cmdName = "New-Foo$($_.Type)"
    Invoke-Command (gcm $cmdName) -InputObject $_

}

但是,我总是收到错误:

  

无法使用指定的命名参数

解析参数集

如您所见,不同的类型意味着设置不同的参数。

我该如何解决这个问题?我想避免手动操作属性,因为在我的现实生活中,我有十几种不同的类型,最多有6个参数。

以下是该问题的完整重复示例:

$csvData = "Type;Title;Param1;Param2`nType1;Foo type 1;ValueForType1;;`nType2;Foo type 2;;ValueForType2"

$csv = ConvertFrom-csv $csvData -Delimiter ';'

$csv | ft -AutoSize

function New-FooType1{
    param(
        [Parameter(Mandatory=$true, ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$Title,
        [Parameter(Mandatory=$true, ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$Param1
    )

    Write-Host "New-FooType1 $Title with $Param1"
}

function New-FooType2{
    param(
        [Parameter(Mandatory=$true, ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$Title,
        [Parameter(Mandatory=$true, ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$Param2
    )

    Write-Host "New-FooType2 $Title with $Param2"
}


$csv | % {
    $cmdName = "New-Foo$($_.Type)"
    Invoke-Command (gcm $cmdName) -InputObject $_

}

此脚本的预期输出为:

New-FooType1 Foo type 1 with ValueForType1
New-FooType2 Foo type 2 with ValueForType2

3 个答案:

答案 0 :(得分:4)

使用呼叫运营商thread.last_message

&

如果您希望参数绑定到特定的命名参数,则调用运算符也支持splatting

$CmdName = "New-FooType1"
$Arguments = "type1"

& $CmdName $Arguments

答案 1 :(得分:2)

要按名称调用命令,您应该使用调用操作符&Invoke-Command cmdlet仅支持ScriptBlock和文件调用,并且仅支持远程调用的文件调用。

对于动态参数绑定,您可以使用spatting,但在这种情况下,您必须将PSCustomObject cmdlet返回的ConvertFrom-Csv转换为Hashtable。您还必须从Hashtable中删除任何额外的参数,因为如果您尝试绑定不存在的参数,则splatting将失败。

动态参数绑定的另一种方法是使用来自管道对象的绑定。它看起来就像你想要做的那样,因为你用ValueFromPipelineByPropertyName选项标记了所有参数。而这种方法只会忽略它无法绑定到参数的任何额外属性。我建议你删除ValueFromPipeline选项,因为如果没有带参数名称的属性,使用此选项PowerShell只会将PSCustomObject转换为字符串(或用于参数的任何类型)并将其作为参数传递给参数值。

因此,您只需要通过管道传递对象并使用invoke运算符来调用具有动态名称的命令:

$_ | & "New-Foo$($_.Type)"

答案 2 :(得分:-2)

不知道你想要做什么,但是 Invoke-Command(gcm $ cmdName)?

尝试使用invoke-expression $ cmdname