本文介绍了使用 CreateProcess 运行批处理文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我正在尝试使用 CreateProcess 来启动一个新的环境块并在新的环境块中运行一个批处理文件.我已经阅读了 CreateProcess 的 msdn 示例,并得出了如下所示的代码.
I am trying to use CreateProcess to start a new environment block and run a batch file in the new environment block. I've read through the msdn example for CreateProcess, and came up with the code shown below.
发生了什么,它会打开新的命令提示符,然后停在那里.由于某种原因,它不会运行我的 .bat 文件.使用 system("CALL path") 将调用 .bat 文件.
What is happening, it will open the new command prompt, and stop there. It will not run my .bat file for some reason. Using system("CALL path") will call the .bat file.
#include <iostream>
#define WINDOWS_LEAN_AND_MEAN
#include <Windows.h>
#include <strsafe.h>
#define BUFSIZE 4096
int main()
{
//system("CALL C:\HFSS\setup_vars.bat");
//return 0;
LPWCH chNewEnv;
LPTSTR lpszCurrentVariable;
DWORD dwFlags = 0;
TCHAR szAppName[] = TEXT("C:\windows\system32\cmd.exe");
TCHAR cmdArgs[] = TEXT("C:\HFSS\setup_var.bat");
STARTUPINFO si;
PROCESS_INFORMATION pi;
BOOL fSuccess;
// Copy environment strings into an environment block.
chNewEnv = GetEnvironmentStrings();
lpszCurrentVariable = (LPTSTR)chNewEnv;
if (FAILED(StringCchCopy(lpszCurrentVariable, BUFSIZE, TEXT("MySetting=A"))))
{
printf("String copy failed
");
return FALSE;
}
lpszCurrentVariable += lstrlen(lpszCurrentVariable) + 1;
if (FAILED(StringCchCopy(lpszCurrentVariable, BUFSIZE, TEXT("MyVersion=2"))))
{
printf("String copy failed
");
return FALSE;
}
// Terminate the block with a NULL byte.
lpszCurrentVariable += lstrlen(lpszCurrentVariable) + 1;
*lpszCurrentVariable = (TCHAR)0;
// Create the child process, specifying a new environment block.
SecureZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
#ifdef UNICODE
dwFlags = CREATE_UNICODE_ENVIRONMENT;
#endif
fSuccess = CreateProcess(szAppName, cmdArgs, NULL, NULL, TRUE, dwFlags,
(LPVOID)chNewEnv, // new environment block
NULL, &si, &pi);
if (!fSuccess)
{
printf("CreateProcess failed (%d)
", GetLastError());
return FALSE;
}
std::cout << "In new environment
";
WaitForSingleObject(pi.hProcess, INFINITE);
return TRUE;
}
推荐答案
一些问题:
- 您需要将
/C
选项传递给cmd.exe
以使其执行 .bat 文件. CreateProcess
的第二个参数必须是可修改的字符串.不是字面意思.- 您需要对文字中的反斜杠字符进行转义.
lpszCurrentVariable
指向GetEnvironmentStrings
返回的缓冲区.您不能修改该缓冲区.您需要分配一个足够长的新缓冲区并将环境复制到其中.然后添加您的修改.- 环境块是双空终止的.标准字符串函数不适用于双空终止字符串.
- 使用
StringCchCopy
之类的函数而不是C 运行时函数只是令人困惑.不要将 MSDN 示例代码视为风格的典范. - C 字符串是要使用的绑定.但是你使用 C++ 所以使用
std::wstring
和其他标准库类和函数. - 您需要在导入
Windows.h
之前定义WINDOWS_LEAN_AND_MEAN
. - 对于 C++,
int main(void)
是不正确的.无参数main
是int main()
.
- You need to pass the
/C
option tocmd.exe
in order to make it execute the .bat file. - The second parameter to
CreateProcess
must be a modifiable string. Not a literal. - You need to escape backslash characters in literals.
lpszCurrentVariable
points to the buffer returned byGetEnvironmentStrings
. You cannot modify that buffer. You need to allocate a new buffer of sufficient length and copy the environment into it. Then add your modifications.- Environment blocks are double null terminated. Standard string functions are of no use with double null terminated strings.
- Using functions like
StringCchCopy
rather than C runtime functions is just confusing. Don't take MSDN example code as being the paragon of style. - C strings are a bind to work with. But you use C++ so use
std::wstring
and other standard library classes and function. - You need to define
WINDOWS_LEAN_AND_MEAN
before importingWindows.h
. - For C++,
int main(void)
is incorrect. The no argumentmain
isint main()
.
以下代码向您展示了如何执行此操作:
The following code shows you how to do this:
#include <cstring>
#include <string>
#include <iostream>
#define WINDOWS_LEAN_AND_MEAN
#include <Windows.h>
std::wstring GetEnvString()
{
wchar_t* env = GetEnvironmentStrings();
if (!env)
abort();
const wchar_t* var = env;
size_t totallen = 0;
size_t len;
while ((len = wcslen(var)) > 0)
{
totallen += len + 1;
var += len + 1;
}
std::wstring result(env, totallen);
FreeEnvironmentStrings(env);
return result;
}
int main()
{
std::wstring env = GetEnvString();
env += L"myvar=boo";
env.push_back(''); // somewhat awkward way to embed a null-terminator
STARTUPINFO si = { sizeof(STARTUPINFO) };
PROCESS_INFORMATION pi;
wchar_t cmdline[] = L"cmd.exe /C C:\Desktop\MyBatFile.bat";
if (!CreateProcess(NULL, cmdline, NULL, NULL, false, CREATE_UNICODE_ENVIRONMENT,
(LPVOID)env.c_str(), NULL, &si, &pi))
{
std::cout << GetLastError();
abort();
}
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
这篇关于使用 CreateProcess 运行批处理文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!