Use CreateProcess to Run a Batch File

user2970916

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.

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\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;
}
David Heffernan

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);
}

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Use Batch File to Run Multiple console applications

From Dev

Use Batch File to Run Multiple console applications

From Dev

Use batch file to run scripts one at a time using conditional statement

From Dev

Batch File Run VBScript

From Dev

Run a shortcut with a batch file

From Dev

Run a shortcut with a batch file

From Dev

How to run this "batch" file?

From Dev

Batch file does not run

From Dev

Run PHP file in batch file

From Dev

Unexpected use of ( batch file

From Dev

How to use `%` in a batch file

From Dev

Unexpected use of ( batch file

From Dev

Run batch as ADMIN & use robocopy

From Dev

Compiled batch file run fullscreen

From Dev

Run Batch file in Visual Basic

From Dev

Compiled batch file run fullscreen

From Dev

Run "./" bash/batch file with cygwin

From Dev

Run Batch File from R

From Dev

run batch file in all subfolders

From Dev

Run a compiled batch file (exe) file through a batch file

From Dev

Error - to run php file using batch file

From Dev

Run a batch file ignoring the variables in the file name

From Dev

how to use c# run batch file as Administrator to install windows services

From Dev

Make batch file run in the background of the command prompt while continuing to use command prompt

From Dev

how to use c# run batch file as Administrator to install windows services

From Dev

How can I use a batch file to run Vagrant commands, but leave me connected to Vagrant once finished?

From Dev

Can I run another batch file in the current batch file windows?

From Dev

Can I run another batch file in the current batch file windows?

From Dev

How to run batch file using Runas command from a batch file

Related Related

HotTag

Archive