【问题标题】:Passing multiple cmd.exe parameters/arguments to ShellExecute(Ex)?将多个 cmd.exe 参数/参数传递给 ShellExecute(Ex)?
【发布时间】:2017-10-02 22:03:14
【问题描述】:

我一直在尝试使用ShellExecuteShellExecuteEx 执行cmd.exe /c /v:on。但是,这两种方法似乎都只接受一个参数,因为当它遇到/v:on时,在Windows 7下会显示一个The filename, directory name, or volume label syntax is incorrect.

这是我尝试过但目前正在搞乱的代码(没有运气):

#include <windows.h>

int main()

{

    SHELLEXECUTEINFO info = {0};

    info.cbSize = sizeof(SHELLEXECUTEINFO);
    info.fMask = SEE_MASK_NOCLOSEPROCESS;
    info.hwnd = NULL;
    info.lpVerb = NULL;
    info.lpFile = "cmd.exe";
    info.lpParameters = "/c /v:on SET example=stackoverflow & ECHO '!example! & pause'";
    info.lpDirectory = NULL;
    info.nShow = SW_SHOW;
    info.hInstApp = NULL;

    ShellExecuteEx(&info);

//  wait for process to terminate
//  WaitForSingleObject(info.hProcess, INFINITE);

    return 0;

}

【问题讨论】:

    标签: c++ cmd parameters shellexecute shellexecuteex


    【解决方案1】:

    由于cmd.exe 是一个可执行文件,您应该使用CreateProcess() 而不是ShellExecuteEx()(无论如何它只是在内部调用CreateProcess(),所以摆脱中间人)。

    无论如何,这不是ShellExecute() 的问题。如果您打开cmd.exe 窗口并输入完整的命令行:

    cmd /c /v:on SET example=stackoverflow & ECHO '!example! & pause'`
    

    你得到完全相同的错误,还有更多:

    cmd /c /v:on SET example=stackoverflow & ECHO '!example! & 暂停' 文件名、目录名或卷标语法不正确。 '!例子! 'pause'' 不是内部或外部命令、可运行程序或批处理文件。

    第一个错误的原因是因为/vcmd.exe本身的参数,不是/C可以执行的单独命令。 /C(或/K)后面的所有内容都是一个新的命令行,所以它必须是调用cmd.exe时指定的最后一个参数。这在/C(和/K)的文档中有说明:

    如果指定了 /C 或 /K,则命令行后面的剩余部分 开关作为命令行处理

    因此,/v:on 被解释为新命令行的第一个参数,因此它被视为显然不存在的文件名。

    交换/V/C参数,第一个错误就消失了:

    cmd /v:on /c SET example=stackoverflow & ECHO '!example! & 暂停' '!例子! 'pause'' 不是内部或外部命令、可运行程序或批处理文件。

    现在,您会注意到!example! 没有按预期扩展。这是因为您没有引用命令行,正如 /C(和 /K)的文档所说:

    请注意,如果字符串用引号括起来,则可以接受由命令分隔符“&&”分隔的多个命令。此外,出于兼容性原因,/X 与/E:ON 相同,/Y 与/E:OFF 相同,/R 与/C 相同。任何其他开关都将被忽略。

    所以,将命令行用引号括起来,然后 !example! 被扩展:

    cmd /v:on /c "SET example=stackoverflow & ECHO '!example! & pause'" '堆栈溢出 'pause'' 不是内部或外部命令、可运行程序或批处理文件。

    最后,pause 没有被正确解释,因为您将它放在 ECHO 的单引号内,而不是作为单独的命令放在外面:

    cmd /v:on /c "SET example=stackoverflow & ECHO '!example!' & 暂停” '堆栈溢出 ' 按任意键继续 。 . .

    然后你可以去掉ECHO的单引号:

    C:\Users\Ryan>cmd /v:on /c "SET example=stackoverflow & ECHO !example! & pause" 堆栈溢出 按任意键继续 。 . .

    【讨论】:

    • 天哪,你是对的! (关于命令在 CMD 下不起作用)... 叹息... 既然您提到了 CreateProcess .... 我可以说我已经尝试过了... 传递一个参数没问题,但额外的参数不是被视为额外的 cmd.exe 参数,这是我试图启用 DelayedExpansion (更不用说可以遵循的任何其他非 cmd 相关命令)。至少你发布的解决方案可以从 CMD 中工作。我还没有用 CreateProcess 试试这个。我会及时通知你的!
    • 我所说的对ShellExecute()CreateProcess() 都同样有效。我都试过了,它们都有效。
    • 嗯......毕竟,为了代码的简单性/可读性,我最终还是使用了 ShellExecute。此外,无论如何,CreateProcess 提供了我的目标甚至不需要的功能。 但是...问题的罪魁祸首/原因(和解决方案)比我想象的要容易。我基本上不得不交换 /c 和 /v:on .... 如果只有我及时注意到了这一点……任何(如何/谁);如果我没有考虑在 SO 上发布/询问我的问题,我很可能不会很快自己弄清楚。所以我非常感谢你的贡献! :-) - 我猜案件已经结案
    • 下次出现问题时,请先尝试阅读文档(在本例中为CMD.EXE /?here
    • 我了解您来自哪里,但您不想知道我在寻找解决方案时打开了(并且已经)打开了多少个浏览器选项卡...您可能不相信它/我,但我是少数几个真正做 RTFM 的人之一。我总是先检查这些东西,然后再考虑在互联网上发布。然而,我很感激你花时间/精力/耐心向我展示了“光”;-) 哦,我最喜欢的 CMD 资源之一也恰好是 SS64.com 和 DosTips(后者,一些众所周知并受到称赞脚本编写者也是 SO 的成员)。
    猜你喜欢
    • 1970-01-01
    • 2021-12-12
    • 1970-01-01
    • 2016-04-02
    • 1970-01-01
    • 2016-07-18
    • 2013-01-07
    • 2011-10-10
    • 2013-09-15
    相关资源
    最近更新 更多