你如何从一个string执行一个任意的本地命令?
我可以用下面的场景expression我的需要: 编写一个函数,接受一个string作为本机命令运行。
这并没有太多的想法:如果你与公司其他地方的其他命令行实用程序进行交互,那么它将提供一个命令来逐字运行。 由于您不控制命令,因此您需要接受任何有效的命令作为input 。 这些是我一直无法克服的主要障碍:
-
该命令可能会执行一个程序,其中有一个空间的path:
$command = '"C:\Program Files\TheProg\Runit.exe" Hello';
-
该命令可能带有空格的参数:
$command = 'echo "hello world!"';
-
该命令可能有单个和双个ticks:
$command = "echo `"it`'s`"";
有没有干净的方式来完成这个? 我只能devise出奢华而丑陋的解决方法,但对于脚本语言,我觉得这应该是简单的。
Invoke-Expression
,也被称为iex
。 以下将在你的例子#2和#3上工作:
iex $command
一些string不会按原样运行,比如您的示例#1,因为exe文件在引号中。 这将按原样工作,因为string的内容正好如何从Powershell命令提示符直接运行:
$command = 'C:\somepath\someexe.exe somearg' iex $command
但是,如果exe文件在引号中,则需要“ &
的帮助才能运行,如本例中的命令行所示:
>> &"C:\Program Files\Some Product\SomeExe.exe" "C:\some other path\file.ext"
然后在脚本中:
$command = '"C:\Program Files\Some Product\SomeExe.exe" "C:\some other path\file.ext"' iex "& $command"
可能的话,通过检测命令string的第一个字符是否“可以处理几乎所有的情况"
,就像在这个天真的实现中一样:
function myeval($command) { if ($command[0] -eq '"') { iex "& $command" } else { iex $command } }
但是你可能会发现一些其他的情况必须以不同的方式被调用。 在这种情况下,您需要使用try{}catch{}
,也许用于特定的exceptiontypes/消息,或者检查命令string。
如果你总是收到绝对path而不是相对path,那么除了上述2之外,你不应该有许多特殊情况(如果有的话)。
关于本质上的微软连接报告,请看看blummin如何使用PowerShell来运行shell命令(呃,讽刺)。
http://connect.microsoft.com/PowerShell/feedback/details/376207/
他们build议使用--%
作为强制PowerShell停止尝试解释文本的方法。
例如:
MSBuild /t:Publish --% /p:TargetDatabaseName="MyDatabase";TargetConnectionString="Data Source=.\;Integrated Security=True" /p:SqlPublishProfilePath="Deploy.publish.xml" Database.sqlproj
尝试parsingregistry中的卸载string时,接受的答案不适用于我,并执行它们。 事实certificate,毕竟我并不需要调用Invoke-Expression
。
我终于遇到了这个很好的模板 ,看看如何执行卸载string:
$path = 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall' $app = 'MyApp' $apps= @{} Get-ChildItem $path | Where-Object -FilterScript {$_.getvalue('DisplayName') -like $app} | ForEach-Object -process {$apps.Set_Item( $_.getvalue('UninstallString'), $_.getvalue('DisplayName')) } foreach ($uninstall_string in $apps.GetEnumerator()) { $uninstall_app, $uninstall_arg = $uninstall_string.name.split(' ') & $uninstall_app $uninstall_arg }
这适用于我,也就是说, $app
是一个内部应用程序,我知道只有两个参数。 对于更复杂的卸载string,您可能需要使用连接运算符 。 另外,我只是使用了一个哈希映射,但实际上,你可能想要使用一个数组。
此外,如果您确实安装了同一应用程序的多个版本,则此卸载程序将一次遍历所有这些应用程序,这会混淆MsiExec.exe
,所以也是如此。