Powershell: Executing powershell script with bool parameter doesnt work

Created on 16 Jun 2017  路  16Comments  路  Source: PowerShell/PowerShell

Steps to reproduce

Run from CMD the following command
powershell -ExecutionPolicy Unrestricted -File .\somescript.ps1 -someParameter $True

In the script itself i have the following line
[Parameter(Mandatory=$true)] [bool] $installSQL

I tried playing with that line and the arguments in many ways, all fail.. i have to turn this into a string and make the string into a bool :\

Expected behavior

Script starting to work.. :)

Actual behavior

Error Message Cannot process
argument transformation on parameter 'installSQL'. Cannot convert value "System.String" to type "System.Boolean".
Boolean parameters accept only Boolean values and numbers, such as $True, $False, 1 or 0.
+ CategoryInfo : InvalidData: (:) [bootstrapImageScript.ps1], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : ParameterArgumentTransformationError,bootstrapImageScript.ps1

Environment data

Name Value
---- -----
PSVersion 5.1.14393.1198
PSEdition Desktop
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}
BuildVersion 10.0.14393.1198
CLRVersion 4.0.30319.42000
WSManStackVersion 3.0
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1

Breaking-Change Committee-Reviewed Resolution-Fixed WG-Interactive-Console

Most helpful comment

@pixelicous expectation is that -Command and -File should behave similarly but that is not the case today and should be investigated

All 16 comments

Workaround:

powershell -Command .\somescript.ps1 -someParameter $True

Related https://github.com/PowerShell/PowerShell/issues/4024 where parameter parsing for -File and -Command differ

@SteveL-MSFT So is this a workaround as this is a known issue or is it working as expected?

@pixelicous expectation is that -Command and -File should behave similarly but that is not the case today and should be investigated

@SteveL-MSFT Ok thanks, hope this issue is solved soon, another thing that might be related.. I am writing a PS script that calls a function from a PSM1 file in the same directory.
When I test in PS ISE i remember to remove-module and extract/reimport the function..

The issue is that a boolean parameter from the main script doesn't get sent to the function correctly.

The main script receives a bool parameter when executed, i set it to $false, i pass that to the function as boolean but it always returns $true, no matter how i input ($false, $False, false, 0) or how i try to read that variable, such as:
if ($boolParam)
if ($boolParam -eq $false)
etc..
it always returns $true!!

The only thing that made it work is switching the bool parameter to switch parameter in the main script, the function the script is calling from module still with "BOOL", and it works now.. just didnt want to open another issue, this all seems to be related

thanks in advance

@pixelicous: We'd need to know more about how you pass that Boolean and how the function is defined in order to diagnose the problem.

On a general note, whenever a _nonempty string_ is cast to [bool], the result is $True - irrespective of the content of the string; e.g., [bool] 'False' yields $True.

However, with a parameter that is properly typed [bool], passing a _string_ is prevented altogether.

@mklement0 All is written in the first post. I wrote how i declare my parameter and how do i call that ps1 script. The string is not empty. i tried running:
"-myParam $true"
"-myParam $True"
"-myParam true"
"-myParam True"
"-myParam 1"

On all i received that same error, when i change that parameter to SWITCH, it goes away (when i specify "-myParam"

Your _original_ problem is explained in #4024 (in short: with -File, whatever value you pass is interpreted as a _string_, whose conversion to [bool] then fails - a known problem).

In a follow-up comment you were complaining about a different issue that you feel is related ("pass that to the function as boolean but it always returns $true"), and that is the one I've requested clarification on.

Generally, using a [switch] parameter is preferable to a [bool] anyway, assuming it has a _reasonable default value_.

@mklement0 hey, sorry im on a vacation and will only return back in around 2 weeks time, thus i cannot answer your exact question.

The reason why i do not use -myParam as a switch is because i'm passing that value between a few functions and tools from a control script. If i use this as a switch ill have to build the execution string with the argument or without, when i use $true or $false, the execution string is always the same with a parameter that changes, easier to read and understand..
Eventually.. i moved things around, i used the SWITCH parameter for the main control script, and BOOL for anything else, and it works now.. except for invoking powershell with -file, that still doesn't work.. but i still think it is related, if i wouldn't have used a SWITCH parameter in the main control but a BOOL one, it just doesnt get passed through.. i think it is looking whether that BOOL variable is filled with a value or not, thus sending back $true everytime although it should have sent back $false

@pixelicous:

No worries re delay.

As an aside (it doesn't solve the -File issue):
There actually is a way to use your command-building technique with [switch] parameters too, but the syntax is not often seen:

  • -Foo:$True is the same as just -Foo

  • -Foo:$False is the same as _not specifying_ -Foo.

I wonder if we should support -switch [bool] syntax as I agree the current -switch:[bool] syntax is not obvious. Should be separate issue we anyone wants to pursue. I'll try to fix this and the -File arg issue next week.

@SteveL-MSFT:

The -switch:[bool] syntax is _awkward_ (presumably because it was tacked on _later_), but _necessary_ for disambiguation:

Consider & { param([switch] $Switch) $Switch } vs. & { param([switch] $Switch, [bool] $Bool) $Switch, $Bool } - how would you distinguish between the two with arguments -switch $true, for instance?

Note that some Unix utilities have solved this problem by adopting the convention of allowing any switch (option) to be prefixed with no to signal negation: for instance, -noswitch would then take the place of -switch:$false.

@mklement0 positional parameters make it problematic for sure. Perhaps a non-breaking change would be to utilize the suggestion feature to suggest the colon syntax when it's not a valid set of parameters

@mklement0 The -switch: [bool] syntax is deliberately awkward as there is really only one scenario for passing an actual parameter to a switch: commands calling commands (which you described nicely in an earlier comment.) If you expect the user to pass an actual parameter, then you should be using boolean. If your cmdlet requires the user to pass arguments to a switch parameter then your cmdlet should be redesigned.

@SteveL-MSFT No we can't support -switch [bool]. The current behavior is fundamental to how the parameter binder works.

-Command and -File are very different operations. -Command gathers all of the arguments into a string and then processes that string as a PowerShell script. On the other hand, -File points at a script and passes the remaining arguments to the process. The application receives these arguments through argv[] as strings. Process creation simply doesn't allow for the parent to pass anything but strings to the child process. The PowerShell runtime does do some interpretation on these strings (e.g. treating strings that start with '-' as parameters instead of arguments) but this is necessarily limited by the lack of type information.

@BrucePay:

The immediate issue here is the current _fundamental inability_ to pass a Boolean value (whether as an actual [bool] parameter of with the -switch:<bool> syntax) when using -File, because such a value is invariably treated as a _string_ (for the reasons you describe), and therefore rejected.
I think that needs to be addressed, such as by accepting _string_ values $true and $false as well (just as it is possible to pass an integer as a string).

-File and -Command are indeed _currently_ very different, but I think they _shouldn't be_ - see https://github.com/PowerShell/PowerShell/issues/4024#issuecomment-311541803

The current implementation makes the two different, but I agree with @mklement0 that there doesn't seem to be a reason from a user experience why it should be different. Using the same code for -Command to collect the args and pass it as a string works for -File with .ps1 scripts, just need some additional code to handle scripts without .ps1 extension.

@PowerShell/powershell-committee the concern of supporting $true and $false is resolved with #4178, the concern regarding the difference between -file and -command in general is by design per #4024

Was this page helpful?
0 / 5 - 0 ratings