Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I pass quoted parameters to PowerShell Invoke-Command and ScripBlocks?

Tags:

powershell

I need to run a ps1 script on a remote computer. The script will be passed a single parameter representing a file name. I have tried many, many different combinations and approaches to passing the parameters to the script block, but I am always getting one error or another when trying to support spaces in the script name and/or file name.

Note: The end result will be running a script on a REMOTE computer using the -ComputerName parameter to Invoke-Command, but for simplicity and testing all the examples run locally.

Given the sample "remote" script

#processFile.ps1
$args[0]     # Just outputs the first parameter passed

The following works when there are no spaces in the name

$cmd = ".\processFile.ps1"
$fn = "someFile.csv"
$sb = [ScriptBlock]::Create("$cmd $fn")
Invoke-Command -ScriptBlock $sb

# Outputs the correct
someFile.csv

However, the following does not work

$cmd = ".\processFile.ps1"
$fn = "some File.csv"
$sb = [ScriptBlock]::Create("$cmd $fn")
Invoke-Command -ScriptBlock $sb

# Outputs the incorrect
some

Obviously, the file name parameter needs to be escaped and passed as "some File.csv". And this can be done with the following:

$cmd = ".\processFile.ps1"
$fn = "some File.csv"
$sb = [ScriptBlock]::Create("$cmd `"$fn`"")   # Notice the escape $fn parameter
Invoke-Command -ScriptBlock $sb

# Outputs the correct
some File.csv

BUT, when I try to extended this space support to the script name, everything falls apart. The following fails

$cmd = ".\processFile.ps1"
$fn = "some File.csv"
$sb = [ScriptBlock]::Create("`"$cmd`" `"$fn`"") # Notice the attempt to escape both parameters

with the following exception

Exception calling "Create" with "1" argument(s): "Unexpected token 'some File.csv' in expression or statement."

Everything I have tried, and there have been many, many different approaches, have resulted in something similar. I just cannot seem to get both parameters to be escaped. (Actually, the problem is more than I cannot escape the first parameter. Some of my attempts have included nested quotes, single quotes, [ScriptBlock]::Create, { }, $executionContext, etc.

like image 215
Jason Avatar asked Dec 27 '22 03:12

Jason


2 Answers

Try this:

$sb = [ScriptBlock]::Create(@"
&'$cmd' '$fn'
"@)
like image 156
mjolinor Avatar answered Dec 29 '22 16:12

mjolinor


For anyone puzzling over the accepted answer by mjolinor, you need to add:

. $sb

For it to actually run the script block.

Additionally, a simpler syntax which seems more readable to me is:

$cmd = @"
&'$cmd' '$fn'
"@
Invoke-Expression $cmd
like image 20
BenP Avatar answered Dec 29 '22 17:12

BenP