Search code examples
windowspowershellpowershell-cmdlet

Execute cmdlet through variable?


I want to use an if \ else statement to determine which cmdlet to run while keeping the same params for both commands:

For example I have this call:

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

But I want to use a variable to determine the verb:

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

OR something like this:

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

I tried the $command version but it failed with this:

At C:\Users\Administrator\Dropbox\projects\deloitte\Suncore\Dev\scripts\az-d eploy.ps1:36 char:13 + -ResourceGroupName $ResourceGroup + ~~~~~~~~~~~~~~~~~~ Unexpected token '-ResourceGroupName' in expression or statement. At C:\Users\Administrator\Dropbox\projects\deloitte\Suncore\Dev\scripts\az-d eploy.ps1:36 char:32 + -ResourceGroupName $ResourceGroup + ~~~~~~~~~~~~~~


Solution

  • To do exactly what you are describing you'd need to wrap the whole command as a string and then call it with Invoke-Expression. For Example:

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

    But I think this isn't a very clear way to write a script. A better option would be to use Splatting, which is where you create a hashtable of the parameters that you can then send the cmdlet via a special @ character with the variable name. For example:

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

    This also has the benefit of avoiding using the backtick character, which is generally encouraged as it's hard to spot and easy to break.