How to pass switch parameter from one powershell script to another?

809 views Asked by At

I have two PowerShell scripts and use them on Linux with PowerShell Core, and want to pass the switch parameter from one.ps1 to second.ps1, but the $args is populated as a string with True and False sub-strings in it, which is not accepted by the second.ps1, as it has validation in param block.

How do I change to make it work? I know I can manually enumerate all the parameters of second.ps1 and make up a command argument string, but considering there are so many parameters in second.ps1, is there a better way ?

My scripts look like this:

# one.ps1
param(
    [string][ValidateSet("value1", "value2")]$para1,
    [switch]$para3 = $false
)

Write-Host "one.ps1: para1=$para1"
Write-Host "one.ps1: para3=$para3"

Write-Host "args=$args"

pwsh ./second.ps1 $args

second.ps1

# second.ps1
param(
    [string][ValidateSet("value1", "value2")]$para1="value1",
    [string][ValidateSet("value3", "value4")]$para2="value3",
    [switch]$para3 = $false,
    [switch]$para4 = $false,
    [switch]$para5 = $false,
    [switch]$para6 = $false,
    [switch]$para7 = $false,
    [switch]$para8 = $false
)

Write-Host "second.ps1: para1=$para1"
Write-Host "second.ps1: para2=$para2"
Write-Host "second.ps1: para3=$para3"
Write-Host "second.ps1: para4=$para4"
Write-Host "second.ps1: para5=$para5"
Write-Host "second.ps1: para6=$para6"
Write-Host "second.ps1: para7=$para7"
Write-Host "second.ps1: para8=$para8"

Here is the command to use them

pwsh one.ps1 -para1 value1 -para2 value3 -para3:true -para4:false

Error message:

one.ps1: para1=value1
one.ps1: para3=True
args=-para2 value3 -para4 False
second.ps1: Cannot validate argument on parameter 'para1'. The argument "False" does not belong to the set "value1,value2" specified by the ValidateSet attribute. Supply an argument that is in the set and then try the command again.
2

There are 2 answers

0
T-Me On

I am sorry but I think passing $args as named parameter for the second script won't be that easy. $args is an array of the arguments. Each argument separated by a whitespace. When you pass $args to the second script it will be counted as one argument at position one. $para1 of the second script will take the whole array as its positional parameter.

function one 
{# one.ps1
    param(
        [string][ValidateSet("value1", "value2")]$para1,
        [switch]$para3 = $false
    )

    Write-Host "one.ps1: para1=$para1"
    Write-Host "one.ps1: para3=$para3"

    Write-Host "args=$args"
    Write-Host "argsType=$($args.GetType().BaseType)"

    $args
}

$arg = one -para1 value1 -para2 value3 -para3:$true -para4:$false

Result:

one.ps1: para1=value1
one.ps1: para3=True
args=-para2 value3 -para4: False
argsType=array

PS D:\test> $arg
-para2
value3
-para4:
False

As you can see -para2 value3 isn't a single string but two strings as part of an array. You could write code to rebuild the named prameter string but I think that will be way more work than just to enumerate them. Another soluten would be to use splatting. However you wold have to provide a hashtable instead of just a string for the first script. Here is a way to call another function with args via splatting.

1
Mathias R. Jessen On

Splat the $PSBoundParameters to pass the arguments bound to declared parameters in one.ps1, splat $args to pass the remaining arguments:

# one.ps1
param(
    [string][ValidateSet("value1", "value2")]$para1,
    [switch]$para3 = $false
)

Write-Host "one.ps1: para1=$para1"
Write-Host "one.ps1: para3=$para3"

Write-Host "args=$args"

pwsh ./second.ps1 @PSBoundParameters @args