我的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工具,这就是我看到我遇到的麻烦。哦,我也需要我的例子中的所有空格(即在括号字符周围需要空格)。
所以经过多次寻找答案后,我求助于你。提前谢谢。
答案 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;