windows - CreateProcess 能够执行批处理文件,但文档说明相反

标签 windows batch-file winapi createprocess

考虑以下文件:

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

请注意,我没有在对 CreateProcess 的任何调用中指定 cmd.exe,而 MSDN says我必须这样做:

To run a batch file, you must start the command interpreter; set lpApplicationName to cmd.exe and set lpCommandLine to the following arguments: /c plus the name of the batch file.

但是,我得到以下输出:

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

这意味着只要在 lpApplicationNamelpCommandLine 中明确指定 .bat 扩展名,批处理文件就会成功启动。这也适用于 .cmd,但不适用于 .vbs。有谁知道这种行为背后的原因以及实践和文档之间的区别?这种行为是“意外”还是在不同的 Windows 版本中持续存在? (我使用的是 Windows 7 HP)文档中是否有任何一点可以从中推断出这种行为?

最佳答案

作为软件开发人员,您不应依赖未记录的行为。即使当你测试它时某些东西工作正常,如果文档说“你必须用另一种方式做”,你通常不得不忘记你的测试,并按照指示去做。否则,您的软件可能会在下一次 Windows 更新时悄无声息地崩溃,甚至包括次要更新。

现在是批处理/vbs 文件。

要运行 CMD/BAT,调用 GetEnvironmentVariable("ComSpec") 获取 cmd.exe 的路径,然后调用 CreateProcess 指定命令=cmd.exe,参数/C path_to_CMD_file arg1 arg2。 如果路径或参数包含空格,则必须将它们包含在引号中。如果路径或参数包含空格包含",替换为^"

要运行 VBS,请调用 ExpandEnvironmentStrings("%windir%\\System32\\cscript.exe") 或 wscript.exe,然后在 .exe 文件的第一个参数中传递 VBS 路径。如果路径或参数包含空格或引号,则相同的规则适用于转义。

关于windows - CreateProcess 能够执行批处理文件,但文档说明相反,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21553379/

相关文章:

Java 和 SetWindowDisplayAffinity

c# - 找出用户属于哪个组

windows - “and”不被识别为内部或外部命令

windows - 通过 Go 写入 Windows 注册表

c++ - 系统()调用流文件的批处理可执行文件使程序在Windows上重置

windows - 远程删除/禁用 Windows 计划任务

c++ - ReadProcessMemory 更快

windows - Windows 并发 tcp/ip 连接的最大数量是多少?

Python 3 不会引发无效文件名的异常

java - 打印时在PC上添加裁剪