通过变量执行cmdlet



我想使用 if else语句确定要运行的cmdlet,同时保留两个命令的相同参数:

例如,我有这个电话:

    New-AzureRmResourceGroupDeployment `
        -ResourceGroupName $ResourceGroup `
        -TemplateFile $TemplateUri `
        -TemplateParameterFile $TemplateParamFile 

,但我想使用一个变量来确定动词:

    $myVerb = if ($booleanTest) {"Test"} else {"New"}
    [$myVerb]-AzureRmResourceGroupDeployment `
         -ResourceGroupName $ResourceGroup `
         -TemplateFile $TemplateUri `
         -TemplateParameterFile $TemplateParamFile 

或类似的东西:

    $command = if ($booleanTest) {"Test-AzureRmResourceGroupDeployment"} else {"New-AzureRmResourceGroupDeployment"}
    $command `
         -ResourceGroupName $ResourceGroup `
         -TemplateFile $TemplateUri `
         -TemplateParameterFile $TemplateParamFile 

我尝试了$command版本,但由于以下方式失败了:

在 C: users indercancer dropbox projects deloitte suncore suncore dev scripts az-d eploy.ps1:36 char:13 -ResourceGroupName $ ResourceGroup + ~~~~~~~~~~~~~~~~~~ Unexpected token '-ResourceGroupName' in expression or statement. At C:UsersAdministratorDropboxprojectsdeloitteSuncoreDevscriptsaz-d eploy.ps1:36 char:32 + -ResourceGroupName $ResourceGroup ~~~~~~~~~~~~~~~

准确地做您所描述的操作,需要将整个命令包裹为字符串,然后用Invoke-Expression调用它。例如:

$MyCommand = "$myVerb-AzureRmResourceGroupDeployment -ResourceGroupName $ResourceGroup -TemplateFile $TemplateUri"
Invoke-Expression $MyCommand

,但我认为这不是编写脚本的非常清晰的方法。一个更好的选择是使用剥离,这是您创建参数的标签,然后可以通过具有变量名称的特殊@字符发送CMDLET。例如:

$AzureParams = @{ 
    ResourceGroupName = $ResourceGroup
    TemplateFile = $TemplateUri
    TemplateParameterFile = $TemplateParamFile 
}
If ($booleanTest) {
    Test-AzureRmResourceGroupDeployment @AzureParams
} Else {
    New-AzureRmResourceGroupDeployment @AzurParams
}

这也具有避免使用反向特征的好处,这通常会受到鼓励,因为很难发现并且易于破裂。

我不建议通过其他答案使用它,而是要直接回答您的问题,请添加调用操作员&

$command = if ($booleanTest) {
    "Test-AzureRmResourceGroupDeployment"
} else {
    "New-AzureRmResourceGroupDeployment"
}
& $command `
     -ResourceGroupName $ResourceGroup `
     -TemplateFile $TemplateUri `
     -TemplateParameterFile $TemplateParamFile 

to 补充现有有用的答案:

  • Invoke-Expression始终是 last Resort ,在这里不需要。使用Invoke-Expression,正确的报价很棘手,并且其使用可能是安全风险(执行任意命令作为字符串执行,类似于Posix的Shell中的eval)。

  • splatting Get-Help about_Splatting)总是值得考虑的:

    • 这是与Mark的答案解释的多行参数通行更强大的替代方案。
    • it 允许逐步构造参数值集及其在多个调用中使用
  • 在手头的情况下,由于命令名称是变量,帕特里克的答案基于 &,呼叫操作员最简单(请参阅Get-Help about_Operators)。


通常,您需要&,每当命令名称 and 无引用的文字(例如,notepad foo.txt工作,'notepad' foo.txt都没有)。

以不同的方式提出:您需要& ,如果您的命令名称是:

  • quotes 中(无论是'...'还是"...");例如,'notepad'
  • 或IS 变量参考;例如,$cmdName
  • expression 的结果(例如, ('get' + '-item')
在这些情况下,需要

&,以便告诉PowerShell您的意图是调用A 命令,而不是评估 expression ;没有&,这种令牌将被解释为启动 expression ;请参阅Get-Help about_Parsing了解 PowerShell的两种基本解析模式,参数模式表达模式


虽然它可能不是最可读的解决方案,因此您甚至可以将可扩展的字符串与嵌入式子表达($(...)-再次,请参见Get-Help about_Operators)结合起来,而无需AUX。变量:

& "$( if ($booleanTest) {'Test'} else {'New'} )-AzureRmResourceGroupDeployment" `
     -ResourceGroupName $ResourceGroup `
     -TemplateFile $TemplateUri `
     -TemplateParameterFile $TemplateParamFile 

使用Mathias R. Jessen建议的分裂:

Function Do-AzureRmResourceGroupDeployment ([ValidateSet("Test", "New")]$Verb, $ResourceGroupName, $TemplateFile, $TemplateParameterFile) {
    $PSBoundParameters.Remove("Verb")
    & "$Verb-AzureRmResourceGroupDeployment" @PSBoundParameters 
}

最新更新