Use Createprocess to Run a Batch File

Use CreateProcess to Run a Batch File

Some problems:

  1. You need to pass the /C option to cmd.exe in order to make it execute the .bat file.
  2. The second parameter to CreateProcess must be a modifiable string. Not a literal.
  3. You need to escape backslash characters in literals.
  4. lpszCurrentVariable points to the buffer returned by GetEnvironmentStrings. 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.
  5. Environment blocks are double null terminated. Standard string functions are of no use with double null terminated strings.
  6. Using functions like StringCchCopy rather than C runtime functions is just confusing. Don't take MSDN example code as being the paragon of style.
  7. C strings are a bind to work with. But you use C++ so use std::wstring and other standard library classes and function.
  8. You need to define WINDOWS_LEAN_AND_MEAN before importing Windows.h.
  9. For C++, int main(void) is incorrect. The no argument main is int 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);
}

Run a batch file using createProcess()

Assumming a standard configuration, the answer is no, it is not required. You can include the batch file in the lpCommandLine argument. The remaining arguments just follow the batch file with quotes where needed.

test.cmd

@echo off
setlocal enableextensions disabledelayedexpansion
echo %1
echo %~1
echo %2
echo %~2

test.c

#define _WIN32_WINNT   0x0500
#include <windows.h>

void main(void){

// Spawn process variables
STARTUPINFO si;
PROCESS_INFORMATION pi;

ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );

CreateProcess(
NULL
, "\"test.cmd\" \"x=1 y=2\" \"x=3 y=4\""
, NULL
, NULL
, TRUE
, 0
, NULL
, NULL
, &si
, &pi
);

WaitForSingleObject( pi.hProcess, INFINITE );
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
};

Output

W:\>test.exe
"x=1 y=2"
x=1 y=2
"x=3 y=4"
x=3 y=4

c++ Execute batch file with createprocess

Below is a pseudo code for running bat in background.

 //... Prepare
//
// Get Current Dir
#define BUFSIZE MAX_PATH
TCHAR myBat[BUFSIZE];
DWORD dwRet;
dwRet = GetCurrentDirectory(BUFSIZE, myBat);

// Append .bat name
myBat += "this_one.bat"

//... Execute
//
STARTUPINFO si = { sizeof(STARTUPINFO) };
PROCESS_INFORMATION pi;

wchar_t cmdline[] = L"cmd.exe /C "+ myBat ;
wchar_t cmdline2[] = L"start /MIN /B \"\" \""+ myBat +"\"";

// For kiosk windows
//wchar_t cmdline[] = L"%systemroot%\\system32\\cmd.exe /C "+ myBat ;

if (!CreateProcess(NULL, cmdline, NULL, NULL, false, CREATE_UNICODE_ENVIRONMENT,
NULL, NULL, &si, &pi))
{
std::cout << GetLastError();
abort();
}

CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);

run batch file with /y using createprocess vs2010

Try this

::CreateProcess(L"cmd.exe", L"/c run.bat /y", NULL, NULL, TRUE, CREATE_NEW_CONSOLE,
NULL, NULL, &startInfo, &procInfo )

As it says on MSDN

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.

Launching a bat file using CreateProcess windows API

Using FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE for dwShareMode parameter of CreateFile API for file handles solves the problem

CreateFile(filehandlepate, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, &secureAttr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

Start windows batch from C++ CreateProcess has different behavior

I just found a solution: I changed the line (in the batch buildMySolution.bat):

call "C:\Program Files(x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat"

to:

call C:\PROGRA~2\micros~1.0\vc\vcvarsall.bat

Believe it or not: using DOS names and removing quotes makes it work!!!

Bug or feature, I'm not sure...



Related Topics



Leave a reply



Submit