将多个 cmd.exe parameters/arguments 传递给 ShellExecute(Ex)?

Passing multiple cmd.exe parameters/arguments to ShellExecute(Ex)?

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

这是我试过的代码,目前正在弄乱(运气不好):

#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=Whosebug & 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;

}

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

无论如何,这都不是 ShellExecute() 问题。如果你打开一个 cmd.exe window 并输入完整的命令行:

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

您得到完全相同的错误,并且更多:

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

The filename, directory name, or volume label syntax is incorrect.
'!example!
'pause'' is not recognized as an internal or external command, operable program or batch file.

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

If /C or /K is specified, then the remainder of the command line after the switch is processed as a command line

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

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

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

'!example!
'pause'' is not recognized as an internal or external command, operable program or batch file.

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

Note that multiple commands separated by the command separator '&&' are accepted for string if surrounded by quotes. Also, for compatibility reasons, /X is the same as /E:ON, /Y is the same as /E:OFF and /R is the same as /C. Any other switches are ignored.

因此,将命令行用引号引起来,然后 !example! 得到扩展:

cmd /v:on /c "SET example=Whosebug & ECHO '!example! & pause'"

'Whosebug
'pause'' is not recognized as an internal or external command, operable program or batch file.

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

cmd /v:on /c "SET example=Whosebug & ECHO '!example!' & pause"

'Whosebug '
Press any key to continue . . .

然后您可以从 ECHO:

中删除单引号
C:\Users\Ryan>cmd /v:on /c "SET example=Whosebug & ECHO !example! & pause"

Whosebug
Press any key to continue . . .