首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何从字符串执行任意本机命令?

如何从字符串执行任意本机命令?
EN

Stack Overflow用户
提问于 2011-06-14 08:54:59
回答 4查看 287.8K关注 0票数 226

我可以通过以下场景来表达我的需求:编写一个函数,该函数接受作为本机命令运行的字符串。

这并不是一个太牵强的想法:如果您正在与公司其他地方的其他命令行实用程序进行交互,这些实用程序会为您提供逐字运行的命令。因为您不能控制命令,所以需要接受任何有效的命令作为输入。以下是我一直无法轻松克服的主要问题:

  1. 该命令可能会执行路径中包含空格的程序:

$command = '"C:\Program Files\TheProg\Runit.exe“Hello‘;

  • 命令中可能有带空格的参数:

$command = 'echo "hello world!“‘;

  • 命令可能同时具有单勾和双勾:

$command = "echo "it's`"";

有没有什么干净的方法可以做到这一点呢?我只能设计出奢侈而丑陋的变通方法,但对于一种脚本语言,我觉得这应该是非常简单的。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-06-14 09:00:09

Invoke-Expression,也被称为iex。下面是你的例子#2和#3:

代码语言:javascript
复制
iex $command

有些字符串不能按原样运行,例如示例#1,因为exe在引号中。这将按原样工作,因为字符串的内容与您直接从Powershell命令提示符运行它的方式完全相同:

代码语言:javascript
复制
$command = 'C:\somepath\someexe.exe somearg'
iex $command

但是,如果可执行文件包含在引号中,则需要&的帮助才能使其运行,如本例所示,从命令行运行:

代码语言:javascript
复制
>> &"C:\Program Files\Some Product\SomeExe.exe" "C:\some other path\file.ext"

然后在脚本中:

代码语言:javascript
复制
$command = '"C:\Program Files\Some Product\SomeExe.exe" "C:\some other path\file.ext"'
iex "& $command"

很可能,您可以通过检测命令字符串的第一个字符是否为"来处理几乎所有的情况,如下面这个简单的实现所示:

代码语言:javascript
复制
function myeval($command) {
    if ($command[0] -eq '"') { iex "& $command" }
    else { iex $command }
}

但您可能会发现其他一些情况必须以不同的方式调用。在这种情况下,您需要使用try{}catch{} (可能针对特定的异常类型/消息),或者检查命令字符串。

如果你总是收到绝对路径而不是相对路径,那么除了上面的两个之外,你不应该有太多的特殊情况。

票数 349
EN

Stack Overflow用户

发布于 2014-02-19 05:32:17

也请看看这篇微软连接报告,本质上,使用PowerShell运行外壳命令是多么的困难(哦,具有讽刺意味)。

http://connect.microsoft.com/PowerShell/feedback/details/376207/

他们建议使用--%作为一种强制PowerShell停止尝试解释右侧文本的方法。

例如:

代码语言:javascript
复制
MSBuild /t:Publish --% /p:TargetDatabaseName="MyDatabase";TargetConnectionString="Data Source=.\;Integrated Security=True" /p:SqlPublishProfilePath="Deploy.publish.xml" Database.sqlproj
票数 21
EN

Stack Overflow用户

发布于 2012-09-11 22:40:24

当我试图解析注册表以卸载字符串并执行它们时,被接受的答案对我不起作用。事实证明,我根本不需要调用Invoke-Expression

我终于看到了这个nice template,看看如何执行卸载字符串:

代码语言:javascript
复制
$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是一个内部应用程序,我知道它只有两个参数。对于更复杂的卸载字符串,您可能需要使用join operator。另外,我只使用了一个散列映射,但实际上,您可能想要使用一个数组。

此外,如果您确实安装了同一应用程序的多个版本,此卸载程序将一次循环所有这些版本,这会使MsiExec.exe感到困惑,因此也存在这一点。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6338015

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档