2

I would like to create a script in powershell, that does several things depending on which parameters is set or not. My code looks like the following:

Param(
    [parameter(Mandatory=$true,Position=1)]
    [String]$var1 ,
    [parameter(Mandatory=$false,Position=2)]
    [int]$var2 ,
    [parameter(Mandatory=$false,Position=3)]
    [int]$var3 ,
    [parameter(Mandatory=$false,Position=4)]
    [string]$var4
)
.... 

And then i want to either do a if-elseif to check which parameters is set:

if (!$var2 -and !$var3 -and !$var4) {
  ... Do something with $var1 
} elseif (!$var2 -and !$var3 -and $var4) {
 ... Do something with $var1 and $var4
} else {
 throw an error
}

.. or do a switch case if that is more suitable. I cant decide whether or not it is. Can anyone come up with a small example to do this? Thanks in advance. And Thank you for taking your time to help me out.

2
  • Good question though I'm not sure if this might be opinion based. Switch is more elegant and easier to read imo. You can also use $PSBoundParameters too. Commented Jul 1, 2021 at 13:09
  • You can also use switch with multiple return statements in addition to Mathias's helpful answer. Commented Jul 1, 2021 at 13:18

2 Answers 2

3

You're looking for the $PSBoundParameters automatic variable - it's a special dictionary/hashtable that contains the argument values passed to the function by the caller:

if(!$PSBoundParameters.ContainsKey('var2') -and !$PSBoundParameters.ContainsKey('var3') -and !$PSBoundParameters.ContainsKey('var4')){
    # only $var1 has an argument value
}

The nice thing about $PSBoundParameters being a hashtable is that if you want to pass optional arguments to another function, you can just splat it:

function Write-CustomHost {
  param(
    [Parameter(Mandatory = $true)]
    $Object,

    [Parameter(Mandatory = $false)]
    [ValidateSet('Red','Green')]
    [string]$ForegroundColor
  )

  Write-Host @PSBoundParameters
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks alot Mathias. That was my first touch on PSBoundParameters. :D Very cool feature.
2

To expand on Mathias great answer, when you have multiple conditions I find the easiest way to do this is to use guard clauses. Guard Clauses are these dead-simple little functions that return a true/false value.

If you string these along in your if blocks, it makes the logic very, very easy to follow. Much easier than repeatedly checking for values from PSBoundParameters, IMHO.

Here's an example.


function isRed {
    param([string]$ForegroundColor)
    $ForegroundColor -eq 'Red'
}

function isInt {
    param($object)
    $object -is [int]
}

These are so simple you may look at them and say 'why even bother'. Here's why!

Once we have them we can call them in a parent function, and since these just return true/false, they fit right into the if condition, like this:

#updating Mathias to add calling the guard clauses
function Write-CustomHost {
  param(
    [Parameter(Mandatory = $true)]
    $Object,

    [Parameter(Mandatory = $false)]
    [ValidateSet('Red','Green')]
    [string]$ForegroundColor
  )

  Write-Host @PSBoundParameters
  
  if (isRed $ForegroundColor -and isInt $Object){
    "this is a red Int, so lets do special handling here"
  }
}

Write-CustomHost -Object 1 -ForegroundColor Red

enter image description here

You can achieve advanced complexity in your code and maintain legibility by implementing simple guard clauses. Others on your team or future you will thank yourself for doing it!

2 Comments

I'd strongly recommend $Object -is [int] in place of $Object.GetType().Name -eq [Int].Name :-)
Good call, I didn't know PowerShell exposed an -is operator!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.