2

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
4
  • powershell.exe -ExecutionPolicy bypass --% "C:\Path\script.ps1 -Arg1 \"SomeValue\" -Arg2 \"1234\" -Arg3 \"Value1\",\"Some Value\",\"Value 2\" -Arg4 $true" Commented Dec 22, 2016 at 16:22
  • Hello PetSerAl, I will be building this programatically, so the values will need to come from the splatted array. Commented Dec 22, 2016 at 17:27
  • It can be done. You just need to apply proper escaping everywhere. Commented Dec 22, 2016 at 18:11
  • So I need to include quotes in the array elements by escaping? I don't understand. Commented Dec 23, 2016 at 16:13

1 Answer 1

2

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
Sign up to request clarification or add additional context in comments.

7 Comments

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?
The script call with splatted arguments fails with "Cannot process argument transformation on parameter 'Arg3'. Cannot convert value to type System.String". Also, the calling script creates a RunOnce call to the script to persist through a reboot. When the script is called again, I get the same errors (see the manual examples in my original post). How can I have an array of values (with spaces) as an argument from a RunOnce/shortcut/Scheduled Task?
powershell -ExecutionPolicy Bypass -NoProfile -Command "& 'pathtoscript' -Arg1 @(1, 2, 3)"
As for the splat failing, make sure you aren't surrounding the array definition with quotes.
My argument declaration looks exactly like yours. The only quotes are around the strings.
|

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.