0

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

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

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

}
4

1 回答 1

3

由于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(and /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"

堆栈溢出
按任意键继续 。. .
于 2017-10-02T22:54:39.430 回答