我正在尝试使用CreateProcess启动新的环境块并在新的环境块中运行批处理文件。我已经阅读了CreateProcess的msdn示例,并提出了如下所示的代码。
发生了什么,它会打开新的命令提示符,然后停在那里。由于某种原因,它不会运行我的.bat文件。使用系统(" CALL路径")将调用.bat文件。
#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\n");
return FALSE;
}
lpszCurrentVariable += lstrlen(lpszCurrentVariable) + 1;
if (FAILED(StringCchCopy(lpszCurrentVariable, BUFSIZE, TEXT("MyVersion=2"))))
{
printf("String copy failed\n");
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)\n", GetLastError());
return FALSE;
}
std::cout << "In new environment\n";
WaitForSingleObject(pi.hProcess, INFINITE);
return TRUE;
}
答案 0 :(得分:15)
一些问题:
/C
选项传递给cmd.exe
才能使其执行.bat文件。CreateProcess
的第二个参数必须是可修改的字符串。不是文字。 lpszCurrentVariable
指向GetEnvironmentStrings
返回的缓冲区。您无法修改该缓冲区。您需要分配一个足够长度的新缓冲区并将环境复制到其中。然后添加您的修改。 StringCchCopy
这样的函数而不是C运行时函数只会令人困惑。不要将MSDN示例代码作为样式的典范。 std::wstring
和其他标准库类和函数。 WINDOWS_LEAN_AND_MEAN
之前定义Windows.h
。int main(void)
不正确。无争论main
是int main()
。以下代码显示了如何执行此操作:
#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('\0'); // 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);
}