McKenning
McKenning

Reputation: 641

Powershell: Pass multiple values (with spaces) to an argument

I have a script that uses multiple arguments, some of which contain spaces. The script is called from another script, so I pass the arguments to it from variables with the calling script.

Calling script:

$script = "C:\Path\script.ps1"
$arg1 = "SomeValue"
$arg2 = "1234"
$arg3 = @("Value1","Some Value","Value 2")
$arg4 = $true
Invoke-Command $script -Arg1 $arg1 -Arg2 $arg2 -Arg3 $arg3 -Arg4 $arg4

The called script looks like this:

param (
[Parameter(Mandatory=$false,Position=0)]
[String]$arg1,
[Parameter(Mandatory=$false,Position=1)]
[String]$arg2,
[Parameter(Mandatory=$false,Position=2)]
[array]$arg3,
[Parameter(Mandatory=$false,Position=3)]
[bool]$arg4
)

# Do stuff with the arguments

When I call the script, I get the following error:

"A positional parameter cannot be found that accepts argument 'Some'."

I've also manually called the script (bypassing the calling script) in a powershell window as below:

powershell.exe -ExecutionPolicy bypass C:\Path\script.ps1 -Arg1 "SomeValue" -Arg2 "1234" -Arg3 @("Value1","Some Value","Value 2") -Arg4 $true

powershell.exe -ExecutionPolicy bypass C:\Path\script.ps1 -Arg1 "SomeValue" -Arg2 "1234" -Arg3 "Value1","Some Value","Value 2" -Arg4 $true

powershell.exe -ExecutionPolicy bypass C:\Path\script.ps1 -Arg1 "SomeValue" -Arg2 "1234" -Arg3 "Value1","SomeValue","Value2" -Arg4 $true

powershell.exe -ExecutionPolicy bypass C:\Path\script.ps1 -Arg1 "SomeValue" -Arg2 "1234" -Arg3 "Value1,SomeValue,Value2" -Arg4 $true

None of these variations work. I've also tried the ideas found here by changing the Arg3 value to (,$args) but that doesn't work. I also changed the parameter type as found here, but that didn't work either.

The goal is to be able to pass multiple variables (some with spaces) to the script through an argument/parameter.

EDIT 12/22/16: The goal includes passing this same information from a shortcut/typed command. For example, my calling script creates a RunOnce entry in the registry to reference the called script and places the arguments in the call just like the manual examples above. None of them work, either.

Set-ItemProperty $RegROPath "(Default)" -Value "powershell.exe -ExecutionPolicy Bypass $scriptPath $argumentList" -type String

Upvotes: 2

Views: 10893

Answers (1)

Patrick Meinecke
Patrick Meinecke

Reputation: 4173

Replace Invoke-Command With & or .

Use & if all you want is output, . if you want it to run in the current context (e.g. retain all variables set)

Get-Help about_Scripts for more detail (or read online version here)

Edit: Forgot to mention, it's not your script that is throwing that error, it's Invoke-Command. If you absolutely have to use Invoke-Command you need (running remotely for example) to pass the arguments as the parameter ArgumentList like this:

$script = "C:\Path\script.ps1"
$argumentList = @(
    '-arg1 "SomeValue"',
    '-arg2 1234',
    '-arg3 @("Value1","Some Value","Value 2")',
    '-arg4 $true'
)
Invoke-Command -FilePath $script -ArgumentList $argumentList

Edit 2:

I will try your suggestion as soon as I am able to. One question, what if I need to add a conditional argument? Currently, I add arguments to the list with $argumentlist += ("arg5", "value"). Some of them are conditional: if ($bool) {$argumentlist += ("arg5", "value")}. Is there a way to do that in your example?

Yes you can, the $argumentList variable in the example is an array like any other. It can be defined all at once, defined empty and added to later, or any mix.

Example

$argumentList = @(
    '-arg1 "SomeValue"',
    '-arg2 1234',
    '-arg3 @("Value1","Some Value","Value 2")',
    '-arg4 $true'
)
if ($bool) {
    $argumentList += '-arg5 "value"'
}
Invoke-Command -FilePath $script -ArgumentList $argumentList

But again, unless you are running the command on a remote computer or PSSession, you should use & or dot sourcing (.). You can still add arguments conditionally using splatting (about_Splatting)

Example

$scriptParamsSplat = @{
    arg1 = "SomeValue"
    arg2 = 1234
    arg3 = @("Value1","Some Value","Value 2")
    arg4 = $true
}
if ($bool) {
    $scriptParamsSplat.arg5 = "value"
}
& 'C:\Path\To\script.ps1' @scriptParamsSplat

Upvotes: 2

Related Questions