22

I have Windows registry key value in wstring format. Now I want to pass it to this code (first argument - path to javaw.exe):

std::wstring somePath(L"....\\bin\\javaw.exe");

    if (!CreateProcess("C:\\Program Files\\Java\\jre7\\bin\\javaw.exe", <--- here should be LPCTSTR, but I have a somePath in wstring format..
            cmdline, // Command line.
            NULL, // Process handle not inheritable.
            NULL, // Thread handle not inheritable.
            0, // Set handle inheritance to FALSE.
            CREATE_NO_WINDOW, // ON VISTA/WIN7, THIS CREATES NO WINDOW
            NULL, // Use parent's environment block.
            NULL, // Use parent's starting directory.
            &si, // Pointer to STARTUPINFO structure.
            &pi)) // Pointer to PROCESS_INFORMATION structure.
    {
        printf("CreateProcess failed\n");
        return 0;
    }

How can I do that?

LihO
  • 41,190
  • 11
  • 99
  • 167
Ernestas Gruodis
  • 8,567
  • 14
  • 55
  • 117

4 Answers4

33

Simply use the c_str function of std::w/string.

See here:

http://www.cplusplus.com/reference/string/string/c_str/

std::wstring somePath(L"....\\bin\\javaw.exe");

    if (!CreateProcess(somePath.c_str(),
            cmdline, // Command line.
            NULL, // Process handle not inheritable.
            NULL, // Thread handle not inheritable.
            0, // Set handle inheritance to FALSE.
            CREATE_NO_WINDOW, // ON VISTA/WIN7, THIS CREATES NO WINDOW
            NULL, // Use parent's environment block.
            NULL, // Use parent's starting directory.
            &si, // Pointer to STARTUPINFO structure.
            &pi)) // Pointer to PROCESS_INFORMATION structure.
    {
        printf("CreateProcess failed\n");
        return 0;
    }
paulm
  • 5,629
  • 7
  • 47
  • 70
  • 5
    This one not working: cannot convert 'const wchar_t*' to 'LPCSTR {aka const char*}' for argument '1' to 'BOOL CreateProcessA(LPCSTR, LPSTR, LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, BOOL, DWORD, PVOID, LPCSTR, LPSTARTUPINFOA, LPPROCESS_INFORMATION)' – Ernestas Gruodis Mar 23 '14 at 00:16
  • 3
    Then use std::string or call CreateProcessW instead of CreateProcessA – paulm Mar 23 '14 at 00:17
  • 2
    If `LPCTSTR` is `const char*` then there's no reason you should be using `std::wstring`. Conversely, if you think you should be using `std::wstring`, set the `UNICODE` flag in your project options. – Mooing Duck Mar 23 '14 at 00:56
12

LPCTSTR is an old relic. It's a hybrid typedef that either defines char* if you are using multi-byte strings or wchar_t* if you are using Unicode. In Visual Studio, this can be changed in general project's settings under "Character Set".

If you are using Unicode, then:

std::wstring somePath(L"....\\bin\\javaw.exe");
LPCTSTR str = somePath.c_str();                 // i.e. std::wstring to wchar_t*

If you are using multi-byte, then use this helper:

// wide char to multi byte:
std::string ws2s(const std::wstring& wstr)
{
    int size_needed = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), int(wstr.length() + 1), 0, 0, 0, 0); 
    std::string strTo(size_needed, 0);
    WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), int(wstr.length() + 1), &strTo[0], size_needed, 0, 0); 
    return strTo;
}

i.e. std::wstring to std::string that will contain multi-byte string and then to char*:

LPCTSTR str = ws2s(somePath).c_str();
LihO
  • 41,190
  • 11
  • 99
  • 167
  • @ErnestasGruodis: You're welcome. In case you are working with Unicode, [>>HERE<<](http://stackoverflow.com/a/19301739/1168156) you will find helper for converting the multi-byte back to `std::wstring` too. – LihO Mar 23 '14 at 00:21
  • 1
    The TCHAR mess is a relic of the WinNT transition, but there's no guarantee std::string will contain multibyte strings, nor does std::wstring use a fixed-length encoding. It would be nice if Microsoft fully supported going the UTF-8 way (a multibyte encoding), but they are committed to going UTF-16 instead (a multi-doublebyte encoding). – Deduplicator Mar 23 '14 at 15:53
1

The safest way when interacting from stdlib classes with TCHARs is to use std::basic_string<TCHAR> and surround raw strings with the TEXT() macro (since TCHAR can be narrow and wide depending on project settings).

std::basic_string<TCHAR> somePath(TEXT("....\\bin\\javaw.exe"));

Since you won't win style contests doing this ... another correct method is to use explicitly the narrow or wide version of a WinAPI function. E.g. in that particular case:

  • with std::string use CreateProcessA (which uses LPCSTR which is a typedef of char*)
  • with std::u16string or std::wstring use CreateProcessW (which uses LPCWSTR which is a typedef of wchar_t*, which is 16-bit in Windows)

In C++17, you could do:

std::filesystem::path app = "my/path/myprogram.exe";
std::string commandcall = app.filename.string() + " -myAwesomeParams";
// define si, pi
CreateProcessA(
    const_cast<LPCSTR>(app.string().c_str()),
    const_cast<LPSTR>(commandcall.c_str()),
    nullptr, nullptr, false, CREATE_DEFAULT_ERROR_MODE, nullptr, nullptr,
    &si, &pi)
Roi Danton
  • 7,933
  • 6
  • 68
  • 80
0

Finally decided to use CreateProcessW as paulm mentioned with a little corrections - values need to be casted (otherwise I get error):

STARTUPINFOW si;
    memset(&si, 0, sizeof (STARTUPINFOW));
    si.cb = sizeof (STARTUPINFOW);
    si.dwFlags = STARTF_USESHOWWINDOW;
    si.wShowWindow = FALSE;

    PROCESS_INFORMATION pi;
    memset(&pi, 0, sizeof (PROCESS_INFORMATION));

    std::wstring cmdline(L" -jar install.jar");

    if (!CreateProcessW((LPCWSTR)strKeyValue.c_str(),
            (LPWSTR)cmdline.c_str(), // Command line.
            NULL, // Process handle not inheritable.
            NULL, // Thread handle not inheritable.
            0, // Set handle inheritance to FALSE.
            CREATE_NO_WINDOW, // ON VISTA/WIN7, THIS CREATES NO WINDOW
            NULL, // Use parent's environment block.
            NULL, // Use parent's starting directory.
            &si, // Pointer to STARTUPINFO structure.
            &pi)) // Pointer to PROCESS_INFORMATION structure.
    {
        printf("CreateProcess failed\n");
        return 0;
    }
Ernestas Gruodis
  • 8,567
  • 14
  • 55
  • 117