考虑以下文件:
a.bat
:
@echo Hello from bat %1
和c.cpp
:
#define UNICODE
#include <windows.h>
#include <stdio.h>
void check(TCHAR *cmd, TCHAR *args) {
STARTUPINFO sinf;
PROCESS_INFORMATION pinf;
memset(&sinf, 0, sizeof sinf);
sinf.cb = sizeof(sinf);
CreateProcess(cmd, args, NULL, NULL, FALSE, 0, NULL, NULL, &sinf, &pinf);
WaitForSingleObject(pinf.hProcess, INFINITE);
}
int main() {
TCHAR cmd1[] = L"a";
TCHAR cmd2[] = L"a.bat";
TCHAR cmdargs1[] = L"a argument";
TCHAR cmdargs2[] = L"a.bat argument";
TCHAR args[] = L"argument";
#define run_check(a, b) printf(#a " + " #b "\n"); fflush(stdout); check(a, b)
run_check(cmd1, cmdargs1);
run_check(cmd1, cmdargs2);
run_check(cmd1, args);
run_check(cmd2, cmdargs1);
run_check(cmd2, cmdargs2);
run_check(cmd2, args);
run_check(NULL, cmdargs1);
run_check(NULL, cmdargs2);
printf("Done\n");
return 0;
}
请注意,我没有在cmd.exe
的任何电话中指定CreateProcess
,而我必须执行MSDN says:
要运行批处理文件,必须启动命令解释程序;将lpApplicationName设置为cmd.exe并将lpCommandLine设置为以下参数:/ c加上批处理文件的名称。
但是,我得到以下输出:
cmd1 + cmdargs1
cmd1 + cmdargs2
cmd1 + args
cmd2 + cmdargs1
Hello from bat argument
cmd2 + cmdargs2
Hello from bat argument
cmd2 + args
"argument" не является внутренней или внешней
командой, исполняемой программой или пакетным файлом.
NULL + cmdargs1
NULL + cmdargs2
Hello from bat argument
Done
这意味着,只要在.bat
或lpApplicationName
中明确指定lpCommandLine
扩展名,就会成功启动批处理文件。这也适用于.cmd
,但不适用于.vbs
。有谁知道这种行为背后的原因以及练习和文档之间的区别?这种行为是“意外”还是在不同的Windows版本中持续存在? (我使用的是Windows 7 HP)文档中是否有任何一点可以推断出这种行为?
答案 0 :(得分:0)
作为软件开发人员,您不应该依赖未记录的行为。即使在测试它时工作正常,如果文档说“你必须以另一种方式做”,你通常必须忘记测试,并按照指示行事。否则,您的软件可能会在下一次Windows更新时无声地崩溃,甚至包括次要更新。
现在在batch / vbs文件上。
要运行CMD / BAT,请调用GetEnvironmentVariable("ComSpec")
以获取cmd.exe的路径,然后调用CreateProcess指定command = cmd.exe
,参数/C path_to_CMD_file arg1 arg2
。
如果路径或参数包含空格,则必须将它们包含在引号中。如果路径或参数包含包含"
的空格,请替换为^"
。
要运行VBS,请调用ExpandEnvironmentStrings("%windir%\\System32\\cscript.exe")
或wscript.exe,然后在.exe文件的第一个参数中传递VBS路径。如果路径或参数包含空格或引号,则相同的规则适用于转义。