Boolean parameter values in a PowerShell script
Asked Answered
P

2

5

I'd like to understand how a PowerShell script handles boolean parameter values.

I have a script with 4 parameters, 2 of which are boolean variables. When I run the script & set one of these parameters to $False, the script still thinks this variable is set to $True.

Version 1: BooleanTest.ps1 (using BOOLEAN parameters)

param(
    [Parameter(Mandatory=$True, Position=1)][string]$param1,
    [Parameter(Mandatory=$True, Position=2)][string]$param2,
    [Parameter(Mandatory=$True, Position=3)][bool]$param3,
    [Parameter(Mandatory=$True, Position=4)][bool]$param4
)

write-output $param1, $param2, $param3, $param4

Running this script from the command prompt returns the following:

>BooleanTest.ps1 -param1 "String1" -param2 "String2" -param3 $True -param4 $False
String1
String2
$True
$True

I've also tried adjusting this script to use switch parameters instead:

Version 2: BooleanTest.ps1 (using SWITCH parameters)

param(
    [Parameter(Mandatory=$True, Position=1)][string]$param1,
    [Parameter(Mandatory=$True, Position=2)][string]$param2,
    [switch]$param3,
    [switch]$param4
)

write-output $param1, $param2, $param3, $param4

Running this version from the command prompt returns:

>BooleanTest.ps1 -param1 "String1" -param2 "String2" -param3:$True -param4:$False
String1
String2

IsPresent
---------
     True
    False

Based on these trials, I have the following questions:

  • In Version 1, why is the fourth variable incorrectly being returned as $True when I declared it as $False?
  • In Version 2, why is the "IsPresent" list being returned?
  • How does the switch statement work? After passing in the variable, do I need to run additional code to assign the True/False value, or can I use the parameter as is?

I've read various several help & troubleshooting articles, but there doesn't seem to be any clear documentation on passing boolean values to a script. I would appreciate any information that would help me understand the proper techniques to apply in this situation.

My System Set-Up:
OS: Windows 10
PowerShell Version: PowerShell 7.1.5

Pontic answered 15/10, 2021 at 19:33 Comment(4)
Version 1 works for me, as expected. Output: String1 String2 True FalseDivision
The IsPresent thing is interesting, normally you use a switch parameter just like a boolean parameter in code. The difference is just in passing explicit $false value. E. g. you can use switch parameter in boolean context like if( $param3 ) { ... } else { ... }Division
Switch parameters. @Division Switch parameters are of type SwitchParameter, which implicitly converts to Boolean.Thicken
@JosefZ, yes. I just have never outputted a switch parameter as-is, so its default output surprised me.Division
A
6

Version 1

This works for me. I get the following output:

String1
String2
True
False

I'm not sure what's going on when you run this, but this is the output expected from what you provided.


Version 2

You are not using bool types, you are using switch types. switch behaves much like a boolean but is not a boolean. When determining truthiness, ultimately the value of IsPresent is considered and not the default behaviors of truthiness. When the switch value is $false or not provided, it evaluates to $false. If the switch value is $true or is provided, it evaluates to $true.

Note: I stated IsPresent is considered when comparing switch to bool. This is an oversimplification and technically incorrect, though you can look at IsPresent to understand how the determination would be made. If you want a more advanced explanation, read on.

The actual reason and "secret sauce" behind the magic is because the SwitchParameter type ([switch] is a type accelerator for SwitchParameter) overloads the == and != comparison operators, and casting operators between bool and switch both ways. These overloads allow switch and bool to functionally behave like the same type during comparisons and allows implicit conversion (typecasting) between the two, despite being completely different ValueTypes.

Most of the time the differences between bool and switch won't matter. You use them the same way in comparisons 99% of the time, save for maybe code intended for debugging when you would actually need to inspect the properties of either.

They also differ in terms of default output, when writing to the console switch has a different display-formatter, which formats the output as a table showing IsPresent by default, unlike the bool type. This, however, is a very minor difference.

Where they mainly differ is in when and how you use them.


When to use switch

switch is best for using with parameter definitions. They are idiomatic to PowerShell in this way and you don't need to provide a $true or $false value with the parameter. You simply specify them or don't like so:

BooleanTest2.ps1 -param1 "String1" -param2 "String2" -param3

This will output the same as your current invocation of your version 2 boolean test. Although as you discovered, you can provide the $true or $false value which is handy when you need to conditionally provide the switch based on another condition.

When to use bool

Conversely, using bool for a parameter is less common and is not considered idiomatic. You have to provide both the parameter and the value the same way you would for any other type. In practice, this generally isn't a problem as long as it's documented but it's something to consider. bool is most often used anywhere else in a script you aren't defining function parameters.

Ana answered 15/10, 2021 at 20:24 Comment(0)
C
0

See here for an explanation.

When running from the command line with your script if you pass -param4 $False it should work. When running from the powershell_ise where you are prompted and you enter $False it does not work as it is treated as a string which is evaluated as true.

Caseinogen answered 16/5, 2023 at 23:53 Comment(1)
Please avoid simply linking to external sites containing the explanation of your answers, since they may not always exist later, and include a complete answer here.Cogitation

© 2022 - 2024 — McMap. All rights reserved.