Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Powershell: Call operator (&) with escape param (--%) not working with non-static args

My Powershell script needs to invoke an EXE with a very complicated set of arguments. I'm using Powershell 3.0, and must stick with that version. Alas, even the "magic" escaping operator (--%) isn't helping me. For example, using the Call operator, consider this:

& other.exe --% action /mode fast /path:"location with spaces" /fancyparam { /dothis /dothat:"arg with spaces" } /verbose

Now, if it were that simple, my script could easily work fine. But it isn't that simple. The arguments for "other.exe" can be different, depending on user selections earlier in my script. So instead, I need to build up those parameters ahead of time, perhaps like this:

$commandArgs = 'action /mode ' + $userMode + ' /path:"location with spaces" /fancyparam { /dothis /dothat:"' + $userArgs + " } /verbose'

Thus I would invoke this way:

& other.exe --% $commandArgs

...well, expect that --% means it just passes a raw string of $commandArgs instead. But without the --%, powershell auto-quotes the contents of $commandArgs, which really messes up the internal quotes (not to mention breaking the 'action' argument at the front that other.exe needs first). In other words, I've already tried embedding the --% inside my $commandArgs string, but the damage is already done by the time it would be parsed (and I don't think it even works that way).

NOTE that this example is only about 1/4 of my actual command I need to execute -- which includes many more user args, quotes and other funny characters that would drive me into escaping-hell in a hurry! I've also already been using the echoargs.exe tool, which is how I'm seeing the troubles I'm having. Oh, and I need all the spaces in my example, too (i.e. need spaces around the brace characters).

So after much searching for an answer, I turn to you for help. Thanks in advance.

like image 874
SteveDJ Avatar asked Jan 27 '14 16:01

SteveDJ


People also ask

What does @() mean in PowerShell?

What is @() in PowerShell Script? In PowerShell, the array subexpression operator “@()” is used to create an array. To do that, the array sub-expression operator takes the statements within the parentheses and produces the array of objects depending upon the statements specified in it.

Why we use $_ in PowerShell?

$_ is a variable created by the system usually inside block expressions that are referenced by cmdlets that are used with pipe such as Where-Object and ForEach-Object . But it can be used also in other types of expressions, for example with Select-Object combined with expression properties.

How do you create a call function in PowerShell?

A simple functionA function in PowerShell is declared with the function keyword followed by the function name and then an open and closing curly brace. The code that the function will execute is contained within those curly braces.

How do you run a Windows PowerShell call?

In File Explorer (or Windows Explorer), right-click the script file name and then select "Run with PowerShell". The "Run with PowerShell" feature starts a PowerShell session that has an execution policy of Bypass, runs the script, and closes the session.


2 Answers

Ok, probably weird to be answering my own question, but after spending another day on this problem yesterday, I might have realized the answer myself. At least, this is what I found that works. But I post here to get further feedback, in case I'm really doing something that isn't recommended ...using Invoke-Expression :-)

I had sorta realized early on, and some of you confirmed this in your responses, that the --% prevents all further expansions (including my $variables). And my problem is that I'm still needing to expand lots of things when trying to use the Call operator (&). My problem would be solved if my command line was all ready to go before using --%, so that's what I did.

I created a new string, composed of:

$fullCommand = '& "other.exe" --% ' + $commandArgs

(The EXE path actually has spaces in it, hence the quotes.) Then, with it all built up (including the --% where it needs to be), I invoke it as a new piece of script:

Invoke-Expression $fullCommand

So far, I'm having very good results. But I know in my search up to this point that Invoke-Expression sounded like this bad thing people shouldn't use. Thoughts, everyone?

like image 100
SteveDJ Avatar answered Oct 24 '22 14:10

SteveDJ


The purpose of --% is to suppress argument processing, so there's no expansion of variables after that parameter on behalf of PowerShell. You can work around this by using environment variables, though:

$env:UserMode = 'foo'
$env:UserArgs = 'bar baz'

& other.exe --% action /mode %UserMode% /path:"location with spaces" /fancyparam { /dothis /dothat:"%userArgs%" } /verbose
like image 31
Ansgar Wiechers Avatar answered Oct 24 '22 16:10

Ansgar Wiechers