Use CreateProcess to Run a Batch File
Some problems:
- 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('\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);
}