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?
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;
}
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();
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;
}
Le moyen le plus sûr lors de l'interaction à partir de classes stdlib avec TCHAR
s 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:
std::string
utilisez CreateProcessA
(qui utilise LPCSTR
qui est un typedef de char*
)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)