Powershell:使用转义参数调用运算符(&)( - %)不使用非静态参数

时间:2014-01-27 16:49:52

标签: powershell parameters escaping call operator-keyword

我的Powershell脚本需要使用一组非常复杂的参数调用EXE。我正在使用Powershell 3.0,并且必须坚持使用该版本。唉,即使是“神奇”逃脱的操作员(--%)也没有帮助我。例如,使用Call运算符,请考虑:

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

现在,如果它很简单,我的脚本可以很容易地正常工作。但事情并非那么简单。 “other.exe”的参数可能不同,具体取决于我脚本中较早的用户选择。所以相反,我需要提前建立这些参数,也许是这样:

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

因此我会这样调用:

& other.exe --% $commandArgs

......好吧,期望--%意味着它只是传递一个原始字符串$commandArgs。但是如果没有--%,powershell会自动引用$ commandArgs的内容,这会真正搞乱内部引用(更不用说破坏其他程序首先需要的前面的'action'参数)。换句话说,我已经尝试在我的$ commandArgs字符串中嵌入--%,但损坏已经在它被解析的时候完成了(我认为它甚至不会那样工作)。 / p>

请注意,这个例子只是我需要执行的实际命令的1/4 - 其中包括更多用户参数,引号和其他有趣的字符,这些字符会让我匆忙逃离地狱!我也一直在使用echoargs.exe工具,这就是我看到我遇到的麻烦。哦,我也需要我的例子中的所有空格(即在括号字符周围需要空格)。

所以经过多次寻找答案后,我求助于你。提前谢谢。

3 个答案:

答案 0 :(得分:8)

好的,回答我自己的问题可能很奇怪,但昨天在这个问题上度过了一天之后,我可能已经意识到答案了。至少,这是我发现的有效。但是我在这里发帖以获得进一步的反馈,以防我真的做了一些不推荐的事情......使用Invoke-Expression: - )

我很早就意识到了,有些人在你的回答中证实了这一点,--%阻止了所有进一步的扩展(包括我的$变量)。我的问题是,在尝试使用Call运算符(&)时,我仍然需要扩展很多东西。如果我的命令行在使用--%之前已准备就绪,我的问题就会解决,这就是我所做的。

我创建了一个新的字符串,由:

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

(EXE路径实际上有空格,因此是引号。)然后,随着它的全部构建(包括它需要的--%),我将其作为新的脚本调用:

Invoke-Expression $fullCommand

到目前为止,我的成绩非常好。但是我知道在我的搜索到目前为止,Invoke-Expression听起来像是人们不应该使用的坏事。想法,每个人?

答案 1 :(得分:3)

--%的目的是抑制参数处理,因此代表PowerShell的参数之后没有变量扩展。但是,您可以使用环境变量解决此问题:

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

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

答案 2 :(得分:2)

我总是建议人们将命令行参数构建到变量中,然后将该变量传递到-ArgumentList cmdlet的Start-Process参数。

$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;