-1

Ive been using the following code to start a bat script.

private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) {

    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:\\Users\\jrowler\\Desktop\\test\\startsimulator.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);

}

This actually works perfectly, but I was wondering if it is possible to take that bat file and somehow include it in my project? Eventually this project will be distributed to a few different people, and I would like it to be set up in such a way that it does not require the user to download a .bat seperately and make sure it stays in the correct location.

Govind Parmar
  • 20,656
  • 7
  • 53
  • 85
Jeremy Rowler
  • 387
  • 1
  • 5
  • 15
  • 2
    Include it as a resource, write it to disk as and when needed. – Alex K. Jan 31 '17 at 13:59
  • you can save the bat file as byte array (or string) , write it in the temp folder and then call it...? – npocmaka Jan 31 '17 at 14:00
  • 1
    Possible duplicate of [How to load a custom binary resource in a VC++ static library as part of a dll?](http://stackoverflow.com/questions/9240188/how-to-load-a-custom-binary-resource-in-a-vc-static-library-as-part-of-a-dll) and [Embed Text File in a Resource in a native Windows Application](http://stackoverflow.com/q/2933295/1889329). – IInspectable Jan 31 '17 at 14:40

1 Answers1

1

You can write the file out using WriteFile. Since you're using C++ you can eschew the <strsafe.h> function I used in my code (I'm used to C) and build an std::wstring containing the file path with standard string operations, and then use the c_str() method to pass the first argument to CreateFile.

char batContent[] = "@echo off\r\necho Hello World\r\n";
wchar_t temp[MAX_PATH], path[MAX_PATH];
GetEnvironmentVariableW(L"Temp", temp, MAX_PATH);
int len = strlen(batContent);
DWORD dwWritten;
StringCchPrintfW(path, MAX_PATH, L"%s\\filename.bat", temp);
HANDLE hFile = CreateFileW(path, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
if(hFile == INVALID_HANDLE_VALUE)
{
      // handle error
}

WriteFile(hFile, batContent, len, &dwWritten, NULL);
CloseHandle(hFile);

// Call CreateProcess with your existing code
Govind Parmar
  • 20,656
  • 7
  • 53
  • 85
  • which function? Im not really used to C, im not sure what I am looking at. – Jeremy Rowler Jan 31 '17 at 14:18
  • `StringCchPrintfW`. – Govind Parmar Jan 31 '17 at 14:19
  • 1
    Passing `FILE_FLAG_DELETE_ON_CLOSE` to the [CreateFile](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858.aspx) is probably a good measure to have it cleaned up even in case the application crashes, or is forcefully closed. Using the user's `%TEMP%` directory is also a good idea to store transient files. – IInspectable Jan 31 '17 at 14:36
  • @IInspectable noted, also, I do use the user's `%TEMP%` directory – Govind Parmar Jan 31 '17 at 14:37
  • Sorry, meant to write to construct a unique filename in the `%TEMP%` directory, using [GetTempFileName](https://msdn.microsoft.com/en-us/library/windows/desktop/aa364991.aspx) for example. – IInspectable Jan 31 '17 at 14:43