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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22585326/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 00:07:56  来源:igfitidea点击:

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

c++stringtype-conversionwstring

提问by Ernestas Gruodis

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

我有wstring格式的Windows 注册表项值。现在我想把它传递给这个代码(第一个参数 - 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?

我怎样才能做到这一点?

回答by paulm

Simply use the c_strfunction of std::w/string.

只需使用c_str的功能std::w/string

See here:

看这里:

http://www.cplusplus.com/reference/string/string/c_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 failed\n");
        return 0;
    }

回答by LihO

LPCTSTRis 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".

LPCTSTR是一个古老的遗迹。它是一个混合 typedef,可以定义char*您是使用多字节字符串还是wchar_t*使用 Unicode。在 Visual Studio 中,这可以在“字符集”下的常规项目设置中更改。

If you are using Unicode, then:

如果您使用的是 Unicode,则:

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::wstringto std::stringthat will contain multi-byte string and then to char*:

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

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

回答by Ernestas Gruodis

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

最后决定使用 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 failed\n");
        return 0;
    }

回答by Roi Danton

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 TCHARcan be narrow and wide depending on project settings).

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

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:

由于这样做不会赢得风格竞赛……另一种正确的方法是明确使用 WinAPI 函数的窄版或宽版。例如在那个特殊情况下:

  • with std::stringuse CreateProcessA(which uses LPCSTRwhich is a typedef of char*)
  • with std::u16stringor std::wstringuse CreateProcessW(which uses LPCWSTRwhich is a typedef of wchar_t*, which is 16-bit in Windows)
  • with std::stringuse CreateProcessA(使用LPCSTR哪个是 的 typedef char*
  • withstd::u16stringstd::wstringuse CreateProcessW(使用LPCWSTRwhich 是 的 typedef wchar_t*,在 Windows 中为 16 位)


In C++17, you could do:

在 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)