如何在c++中将std::wstring转换为LPCTSTR

How to convert std::wstring to LPCTSTR in C++?

本文关键字:wstring 转换 LPCTSTR std c++ 中将      更新时间:2023-10-16

我有wstring格式的Windows注册表键值。现在我想把它传递给下面的代码(第一个参数- java .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 failedn");
        return 0;
    }

我该怎么做呢?

直接使用std::w/stringc_str函数

看到:

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 failedn");
        return 0;
    }

LPCTSTR是一个古老的遗迹。这是一个混合类型定义,如果使用多字节字符串,则定义char*;如果使用Unicode,则定义wchar_t*。在Visual Studio中,这可以在一般项目的"字符集"设置下进行更改。

如果使用Unicode,则:

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

如果您使用多字节,那么使用以下帮助:

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

std::wstringstd::string将包含多字节字符串,然后到char*:

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

从stdlib类与TCHAR s交互时最安全的方法是使用std::basic_string<TCHAR>并将原始字符串与TEXT()宏包围(因为TCHAR可以根据项目设置窄和宽)。

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

既然你这样做不会赢得风格比赛…另一种正确的方法是显式地使用WinAPI函数的窄版本或宽版本。例如:

  • std::string使用CreateProcessA(它使用LPCSTR,这是char*的类型定义)
  • std::u16stringstd::wstring使用CreateProcessW(使用LPCWSTR,这是wchar_t*的类型定义,在Windows中是16位)

在c++ 17中,你可以这样做:

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)

最后决定使用CreateProcessW作为paulm提到的一点更正-值需要被强制转换(否则我会得到错误):

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 failedn");
        return 0;
    }