diff --git a/code/nel/include/nel/misc/common.h b/code/nel/include/nel/misc/common.h index 10f6a97e6..028fc0b0d 100644 --- a/code/nel/include/nel/misc/common.h +++ b/code/nel/include/nel/misc/common.h @@ -349,6 +349,10 @@ std::string formatThousands(const std::string& s); /// The program will be launched in the current directory bool launchProgram (const std::string &programName, const std::string &arguments, bool log = true); +/// This function executes a program and wait for result (used for example for crash report). +/// The program will be launched in the current directory +sint launchProgramAndWaitForResult (const std::string &programName, const std::string &arguments, bool log = true); + /// This function executes a program and returns output as a string std::string getCommandOutput(const std::string &command); diff --git a/code/nel/src/misc/common.cpp b/code/nel/src/misc/common.cpp index 698f9d9ee..3f6a5c7b6 100644 --- a/code/nel/src/misc/common.cpp +++ b/code/nel/src/misc/common.cpp @@ -826,6 +826,90 @@ bool launchProgram(const std::string &programName, const std::string &arguments, return false; +sint launchProgramAndWaitForResult(const std::string &programName, const std::string &arguments, bool log) +{ + sint res = 0; + +#ifdef NL_OS_WINDOWS + STARTUPINFOA si; + PROCESS_INFORMATION pi; + + memset(&si, 0, sizeof(si)); + memset(&pi, 0, sizeof(pi)); + + si.cb = sizeof(si); + + // Enable nlassert/nlstop to display the error reason & callstack + const TCHAR *SE_TRANSLATOR_IN_MAIN_MODULE = _T("NEL_SE_TRANS"); + TCHAR envBuf [2]; + if ( GetEnvironmentVariable( SE_TRANSLATOR_IN_MAIN_MODULE, envBuf, 2 ) != 0) + { + SetEnvironmentVariable( SE_TRANSLATOR_IN_MAIN_MODULE, NULL ); + } + + string arg = " " + arguments; + BOOL ok = CreateProcessA(programName.c_str(), (char*)arg.c_str(), NULL, NULL, FALSE, CREATE_DEFAULT_ERROR_MODE | CREATE_NO_WINDOW, NULL, NULL, &si, &pi); + + if (ok) + { + // Successfully created the process. Wait for it to finish. + WaitForSingleObject(pi.hProcess, INFINITE); + + // Get the exit code. + DWORD exitCode = 0; + ok = GetExitCodeProcess(pi.hProcess, &exitCode); + + //nldebug("LAUNCH: Successful launch '%s' with arg '%s'", programName.c_str(), arguments.c_str()); + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + + if (ok) + { + res = (sint)exitCode; + } + else + { + if (log) + nlwarning("LAUNCH: Failed launched '%s' with arg '%s'", programName.c_str(), arguments.c_str()); + } + } + else + { + LPVOID lpMsgBuf; + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL); + + if (log) + nlwarning("LAUNCH: Failed launched '%s' with arg '%s' err %d: '%s'", programName.c_str(), arguments.c_str(), GetLastError(), lpMsgBuf); + + LocalFree(lpMsgBuf); + + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + } +#else + // save LD_LIBRARY_PATH + const char *previousEnv = getenv("LD_LIBRARY_PATH"); + + // clear LD_LIBRARY_PATH to avoid problems with Steam Runtime + setenv("LD_LIBRARY_PATH", "", 1); + + // program name is the only required string + std::string command = programName; + + // only appends arguments if any + if (!arguments.empty()) command += " " + arguments; + + // execute the command + res = system(command.c_str()); + + // restore previous LD_LIBRARY_PATH + setenv("LD_LIBRARY_PATH", previousEnv, 1); + + if (res && log) + nlwarning ("LAUNCH: Failed launched '%s' with arg '%s' return code %d", programName.c_str(), arguments.c_str(), res); +#endif + + return res; } std::string getCommandOutput(const std::string &command)