Powershell: Call operator (&) with escape param (--%) not working with non-static args
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?
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
I always recommend that people build their command line arguments into a variable, and then pass that variable into the -ArgumentList
parameter of the Start-Process
cmdlet.
$Program = '{0}\other.exe' -f $PSScriptRoot;$UserMode = 'fast';$Path = 'c:\location with\spaces';$ArgWithSpaces = 'arg with spaces';$ArgumentList = 'action /mode {0} /path:"{1}" /fancyparam { /dothis /dothat:"{2}" } /verbose' -f $UserMode, $Path, $ArgWithSpaces;$Output = '{0}\{1}.log' -f $env:Temp, [System.Guid]::NewGuid().ToString();Start-Process -Wait -FilePath $Program -ArgumentList $ArgumentList -RedirectStandardOutput $Output;