web-dev-qa-db-fra.com

Comment convertir std :: wstring en LPCTSTR en C ++?

J'ai une valeur de clé de registre Windows au format wstring. Maintenant, je veux le passer à ce code (premier argument - chemin vers 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;
    }

Comment puis je faire ça?

18
Ernestas Gruodis

Utilisez simplement le c_str fonction de std::w/string.

Vois ici:

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;
    }
24
paulm

LPCTSTR est une ancienne relique. C'est un typedef hybride qui définit soit char* si vous utilisez des chaînes multi-octets ou wchar_t* si vous utilisez Unicode. Dans Visual Studio, cela peut être modifié dans les paramètres généraux du projet sous "Jeu de caractères".

Si vous utilisez Unicode, alors:

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

Si vous utilisez plusieurs octets, utilisez cet assistant:

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

c'est à dire. std::wstring à std::string qui contiendra une chaîne de plusieurs octets, puis à char*:

LPCTSTR str = ws2s(somePath).c_str();
9
LihO

J'ai finalement décidé d'utiliser CreateProcessW comme Paul l'a mentionné avec quelques petites corrections - les valeurs doivent être castées (sinon j'obtiens une erreur):

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;
    }
0
Ernestas Gruodis

Le moyen le plus sûr lors de l'interaction à partir de classes stdlib avec TCHARs est d'utiliser std::basic_string<TCHAR> Et d'entourer les chaînes brutes avec la macro TEXT() (puisque TCHAR peut être étroit et large en fonction des paramètres du projet).

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

Comme vous ne gagnerez pas de concours de style en faisant cela ... une autre méthode correcte consiste à utiliser explicitement la version étroite ou large d'une fonction WinAPI. Par exemple. dans ce cas particulier:

  • avec std::string utilisez CreateProcessA (qui utilise LPCSTR qui est un typedef de char*)
  • avec std::u16string ou std::wstring utilisez CreateProcessW (qui utilise LPCWSTR qui est un typedef de wchar_t*, qui est 16 bits sous Windows)

En C++ 17, vous pourriez faire:

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)
0
Roi Danton