Reputation: 6353
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
+ ~~~~~~~~~~~~~~
Upvotes: 3
Views: 189
Reputation: 437197
To complement the existing helpful answers:
Invoke-Expression
should always be the last resort and is not needed here. With Invoke-Expression
, it is tricky to get the quoting right, and its use can be a security risk (execution of arbitrary commands passed as a string, analogous to eval
in POSIX-like shells).
Splatting (Get-Help about_Splatting
) is always worth considering:
In the case at hand, however, since only the command name is variable, Patrick's answer based on &
, the call operator is simplest (see Get-Help about_Operators
).
Generally, you need &
whenever the command name is not an unquoted literal (e.g., notepad foo.txt
works, but 'notepad' foo.txt
doesn't).
To put it differently: you need &
, if your command name is:
'...'
or "..."
); e.g., 'notepad'
$cmdName
('get' + '-item')
&
is needed in theses case in order to tell PowerShell that your intent is to invoke a command as opposed to evaluating an expression; without &
, such tokens would be interpreted as starting an expression; see Get-Help about_Parsing
to learn about PowerShell's two fundamental parsing modes, argument mode and expression mode.
While it may not be the most readable solution, you can therefore even combine an expandable string with an embedded subexpression ($(...)
- again, see Get-Help about_Operators
) to get away without the need for an aux. variable:
& "$( if ($booleanTest) {'Test'} else {'New'} )-AzureRmResourceGroupDeployment" `
-ResourceGroupName $ResourceGroup `
-TemplateFile $TemplateUri `
-TemplateParameterFile $TemplateParamFile
Upvotes: 2
Reputation: 23633
Using Splatting as suggested by Mathias R. Jessen:
Function Do-AzureRmResourceGroupDeployment ([ValidateSet("Test", "New")]$Verb, $ResourceGroupName, $TemplateFile, $TemplateParameterFile) {
$PSBoundParameters.Remove("Verb")
& "$Verb-AzureRmResourceGroupDeployment" @PSBoundParameters
}
Upvotes: 0
Reputation: 4173
I don't recommend using this over the other answer but to directly answer your question, add the invocation operator &
$command = if ($booleanTest) {
"Test-AzureRmResourceGroupDeployment"
} else {
"New-AzureRmResourceGroupDeployment"
}
& $command `
-ResourceGroupName $ResourceGroup `
-TemplateFile $TemplateUri `
-TemplateParameterFile $TemplateParamFile
Upvotes: 3
Reputation: 23355
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.
Upvotes: 6