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
Community
  • 1
  • 1
McKenning
  • 631
  • 4
  • 20
  • 32

1 Answers1

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
Patrick Meinecke
  • 3,963
  • 2
  • 18
  • 26
  • 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? – McKenning Dec 22 '16 at 00:44
  • 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? – McKenning Dec 22 '16 at 16:45
  • `powershell -ExecutionPolicy Bypass -NoProfile -Command "& 'pathtoscript' -Arg1 @(1, 2, 3)"` – Patrick Meinecke Dec 22 '16 at 16:46
  • As for the splat failing, make sure you aren't surrounding the array definition with quotes. – Patrick Meinecke Dec 22 '16 at 16:49
  • My argument declaration looks exactly like yours. The only quotes are around the strings. – McKenning Dec 22 '16 at 16:52
  • Oh the error is that it's trying to convert it **to** a string not from. Did you change the parameter definition from [array] to [string]? – Patrick Meinecke Dec 22 '16 at 17:16
  • I had changed it to troubleshoot something else and thought I changed it back, but it was a different param that got changed. 1st call working now. For the RunOnce call, to make sure I understand your response above, there is only one argument? How does that translate from the splatted argument list above? Do the numbers represent values in the array? – McKenning Dec 22 '16 at 17:29