void ProcessWin::ForkAndExec() { nativeIn->CreateHandles(); nativeOut->CreateHandles(); nativeErr->CreateHandles(); STARTUPINFO startupInfo; startupInfo.cb = sizeof(STARTUPINFO); startupInfo.lpReserved = NULL; startupInfo.lpDesktop = NULL; startupInfo.lpTitle = NULL; startupInfo.dwFlags = STARTF_FORCEOFFFEEDBACK | STARTF_USESTDHANDLES; startupInfo.cbReserved2 = 0; startupInfo.lpReserved2 = NULL; //startupInfo.hStdInput = nativeIn->GetReadHandle(); //startupInfo.hStdOutput = nativeOut->GetWriteHandle(); //startupInfo.hStdError = nativeErr->GetWriteHandle(); HANDLE hProc = GetCurrentProcess(); nativeIn->DuplicateRead(hProc, &startupInfo.hStdInput); nativeOut->DuplicateWrite(hProc, &startupInfo.hStdOutput); nativeErr->DuplicateWrite(hProc, &startupInfo.hStdError); std::string commandLine(ArgListToString(args)); std::wstring commandLineW(::UTF8ToWide(commandLine)); logger->Debug("Launching: %s", commandLine.c_str()); PROCESS_INFORMATION processInfo; BOOL rc = CreateProcessW(NULL, (wchar_t*) commandLineW.c_str(), NULL, NULL, TRUE, CREATE_NO_WINDOW, // If this is a console application, NULL, // don't open a console window. NULL, &startupInfo, &processInfo); //CloseHandle(nativeIn->GetReadHandle()); CloseHandle(startupInfo.hStdInput); CloseHandle(startupInfo.hStdOutput); CloseHandle(startupInfo.hStdError); if (!rc) { std::string message = "Error launching: " + commandLine; logger->Error(message); throw ValueException::FromString(message); } else { CloseHandle(processInfo.hThread); this->pid = processInfo.dwProcessId; this->process = processInfo.hProcess; this->running = true; } }
static bool runWithQtInEnvironment(const QString &cmd) { enum { timeOutMs = 30000 }; static const bool pathSet = prependPath(); if (!pathSet) return false; STARTUPINFO si; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); STARTUPINFO myInfo; GetStartupInfo(&myInfo); si.hStdInput = myInfo.hStdInput; si.hStdOutput = myInfo.hStdOutput; si.hStdError = myInfo.hStdError; PROCESS_INFORMATION pi; ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); QScopedArrayPointer<wchar_t> commandLineW(new wchar_t[cmd.size() + 1]); cmd.toWCharArray(commandLineW.data()); commandLineW[cmd.size()] = 0; if (!CreateProcessW(0, commandLineW.data(), 0, 0, /* InheritHandles */ TRUE, 0, 0, 0, &si, &pi)) { fprintf(stderr, "Unable to execute \"%s\": %s\n", qPrintable(cmd), qPrintable(errorString(GetLastError()))); return false; } DWORD exitCode = 1; switch (WaitForSingleObject(pi.hProcess, timeOutMs)) { case WAIT_OBJECT_0: GetExitCodeProcess(pi.hProcess, &exitCode); break; case WAIT_TIMEOUT: fprintf(stderr, "Timed out after %d ms out waiting for \"%s\".\n", int(timeOutMs), qPrintable(cmd)); TerminateProcess(pi.hProcess, 1); break; default: fprintf(stderr, "Error waiting for \"%s\": %s\n", qPrintable(cmd), qPrintable(errorString(GetLastError()))); TerminateProcess(pi.hProcess, 1); break; } CloseHandle(pi.hThread); CloseHandle(pi.hProcess); return exitCode == 0; }
// runProcess: Run a command line process (replacement for QProcess which // does not exist in the bootstrap library). bool runProcess(const QString &binary, const QStringList &args, const QString &workingDirectory, unsigned long *exitCode, QByteArray *stdOut, QByteArray *stdErr, QString *errorMessage) { if (exitCode) *exitCode = 0; STARTUPINFO si; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); STARTUPINFO myInfo; GetStartupInfo(&myInfo); si.hStdInput = myInfo.hStdInput; si.hStdOutput = myInfo.hStdOutput; si.hStdError = myInfo.hStdError; PROCESS_INFORMATION pi; ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); const QChar backSlash = QLatin1Char('\\'); QString nativeWorkingDir = QDir::toNativeSeparators(workingDirectory.isEmpty() ? QDir::currentPath() : workingDirectory); if (!nativeWorkingDir.endsWith(backSlash)) nativeWorkingDir += backSlash; if (stdOut) { si.hStdOutput = createInheritableTemporaryFile(); if (si.hStdOutput == INVALID_HANDLE_VALUE) { if (errorMessage) *errorMessage = QStringLiteral("Error creating stdout temporary file"); return false; } si.dwFlags |= STARTF_USESTDHANDLES; } if (stdErr) { si.hStdError = createInheritableTemporaryFile(); if (si.hStdError == INVALID_HANDLE_VALUE) { if (errorMessage) *errorMessage = QStringLiteral("Error creating stderr temporary file"); return false; } si.dwFlags |= STARTF_USESTDHANDLES; } // Create a copy of the command line which CreateProcessW can modify. QString commandLine; appendToCommandLine(binary, &commandLine); foreach (const QString &a, args) appendToCommandLine(a, &commandLine); if (optVerboseLevel > 1) std::wcout << "Running: " << commandLine << '\n'; QScopedArrayPointer<wchar_t> commandLineW(new wchar_t[commandLine.size() + 1]); commandLine.toWCharArray(commandLineW.data()); commandLineW[commandLine.size()] = 0; if (!CreateProcessW(0, commandLineW.data(), 0, 0, /* InheritHandles */ TRUE, 0, 0, (wchar_t *)nativeWorkingDir.utf16(), &si, &pi)) { if (stdOut) CloseHandle(si.hStdOutput); if (stdErr) CloseHandle(si.hStdError); if (errorMessage) *errorMessage = QStringLiteral("CreateProcessW failed: ") + winErrorMessage(GetLastError()); return false; } WaitForSingleObject(pi.hProcess, INFINITE); CloseHandle(pi.hThread); if (exitCode) GetExitCodeProcess(pi.hProcess, exitCode); CloseHandle(pi.hProcess); if (stdOut) readTemporaryProcessFile(si.hStdOutput, stdOut); if (stdErr) readTemporaryProcessFile(si.hStdError, stdErr); return true; }