CreateProcess能够执行批处理文件,但是文档却相反 [英] CreateProcess is able to execute batch files, but documentation says the opposite

查看:85
本文介绍了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

Note that I haven't specified cmd.exe in any of calls to CreateProcess, while MSDN says that I have to do it:

要运行批处理文件,必须启动命令解释器.将lpApplicationName设置为cmd.exe,并将lpCommandLine设置为以下参数:/c加上批处理文件的名称.

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.

但是,我得到以下输出:

However, I get the following output:

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)文档中是否可以从中推断出这种行为?

This means that whenever .bat extension is explicitly specified either in lpApplicationName or lpCommandLine, batch file is successfully started. This works wit .cmd too, but not with .vbs. Does anyone know reason behind such behavior and difference between practice and documentation? Is such behavior 'an accident' or it persists among different Windows versions? (I use Windows 7 HP) Is there any point in documentation from which one can infer such behavior?

推荐答案

作为软件开发人员,您不应依赖未记录的行为.即使您在进行测试时工作正常,但如果文档中指出您必须以另一种方式进行测试",则通常必须忘记进行测试,并按照指示进行操作.否则,您的软件会随着下一个Windows更新(包括次要更新)的出现而自动崩溃.

As a software developer, you shouldn’t rely on undocumented behavior. Even if something works fine when you test it, if the documentation says "you must do it another way", you generally have to forget your tests, and do as instructed. Otherwise your software can silently break down with the next windows update, including even the minor update.

现在在批处理/vbs文件上.

Now on the batch/vbs files.

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

To run the CMD/BAT, call GetEnvironmentVariable("ComSpec") to obtain path to cmd.exe, then call CreateProcess specifying command=cmd.exe, arguments /C path_to_CMD_file arg1 arg2. If the path or arguments contain space, you must include them in quotes. If the path or arguments contain spaces contain ", replace with ^".

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

To run VBS, call ExpandEnvironmentStrings("%windir%\\System32\\cscript.exe") or wscript.exe, then pass VBS path in the first argument of the .exe file. If the path or an argument contain spaces or quotes, same rules apply to escaping.

这篇关于CreateProcess能够执行批处理文件,但是文档却相反的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆