After testing under windows, it is found that QT program will kill the process created by CreateProcess when it exits again
-
MinGW32,After testing under windows, it is found that QT program will kill the process created by CreateProcess when it exits again,I tested the following situations, but there were no exceptions(windows下经过测试发现QT编写的程序再退出的时候会把CreateProcess创建的进程杀死,我测试了以下各种情况但都没有例外),following code:
#include "bccmainwindow.h"
#include "ui_bccmainwindow.h"
#include <QProcess>
#include <QDebug>
#include <QDir>
//#include <windows.h>
#include "qsystemlibrary.h"static QString qt_create_commandline(const QString &program, const QStringList &arguments);
static bool startDetachedUacPrompt(const QString &programIn, const QStringList &arguments,
const QString &workingDir, qint64 *pid);
bool startDetached(const QString &program, const QStringList &arguments, const QString &workingDir, qint64 *pid);using namespace std;
BccMainWindow::BccMainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::BccMainWindow)
{
ui->setupUi(this);
}BccMainWindow::~BccMainWindow()
{
delete ui;
}void BccMainWindow::on_pushButton_clicked()
{QProcess* process = new QProcess; //QString strpath = qApp->applicationDirPath(); //process->setWorkingDirectory(strpath + QString("/softwares/com2tcp")); //QString str_exePath = "\"" + str_exePath + "\""; QStringList arguments; arguments << "-new" << "http://www.qq.com"; if (process->state() != QProcess::Running) { /// 只允许开启一个进程 process->startDetached("C:\\Program Files (x86)\\Internet Explorer\\iexplore.exe ", arguments); // 将以阻塞的方式启动 //process->start("C:\\Program Files (x86)\\Internet Explorer\\iexplore.exe ", arguments); if(!process->waitForStarted()) { qDebug() << "waitForStarted false"; } //process->waitForFinished(5000); QString strResult = QString::fromLocal8Bit(process->readAllStandardOutput()); qDebug() << strResult; } if(process) { //process->close(); delete process; process = NULL; }
}
void BccMainWindow::on_pushButton_2_clicked()
{
QDir::setCurrent("C:\Program Files (x86)\Internet Explorer\");QStringList arguments; arguments << "-new" << "http://www.qq.com"; if(!QProcess::startDetached("iexplore.exe",arguments)) { qDebug() << "startDetached false"; }
}
void BccMainWindow::on_pushButton_3_clicked()
{
/*
QDir::setCurrent("C:\Program Files (x86)\Internet Explorer\");
int code=QProcess::execute("iexplore.exe -new www.qq.com");qDebug() << "execute code "<<code; */ /*
#define SW_NORMAL 1 //普通方式运行
#define SW_SHOWMINIMIZED 2 //运行时最小化显示
#define SW_SHOWMAXIMIZED 3 //运行时最大化显示
#define SW_MAXIMIZE 3 //最大化运行
*/
WinExec(""C:\Program Files (x86)\Internet Explorer\iexplore.exe" -new www.qq.com",1);}
void BccMainWindow::on_pushButton_4_clicked()
{
QDir::setCurrent("C:\Program Files (x86)\Internet Explorer\");QStringList arguments; arguments << "-new" << "http://www.qq.com"; if(!QProcess::execute("iexplore.exe",arguments)) { qDebug() << "execute false"; }
}
/*
QProcess ps;connect(&ps,SIGNAL(readyReadStandardOutput()),this,SLOT(readProcessStandardOutput()));
QStringList args;
args<<"-c";
args<<"ps | grep 'processName";
ps.start("sh",args);
readProcessStandardOutput()
{
ps.readAllStandardOutput() // 得到sh -c "ps | grep 'processName‘“ 的输出结果,查看这个结果就可以得到这个结果是否在运行。}
*/void BccMainWindow::on_pushButton_cmd_clicked()
{
QDir::setCurrent("C:\Program Files (x86)\Internet Explorer\");QStringList arguments; arguments<<"/c"<<"iexplore.exe -new \"http://www.qq.com\""; qint64 pid; //if(!QProcess::startDetached("cmd",arguments,"C:\\Program Files (x86)\\Internet Explorer\\",&pid)) if(!startDetached("cmd",arguments,"C:\\Program Files (x86)\\Internet Explorer\\",&pid)) { qDebug() << "startDetached false"; } /* qint64 ProcessId; HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pid); if (hProcess == NULL) { //return FALSE; } if (!TerminateProcess(hProcess, 0)) { //return FALSE; } */ //return TRUE;
}
static QString qt_create_commandline(const QString &program, const QStringList &arguments)
{
QString args;
if (!program.isEmpty()) {
QString programName = program;
if (!programName.startsWith(QLatin1Char('"')) && !programName.endsWith(QLatin1Char('"')) && programName.contains(QLatin1Char(' ')))
programName = QLatin1Char('"') + programName + QLatin1Char('"');
programName.replace(QLatin1Char('/'), QLatin1Char('\'));// add the prgram as the first arg ... it works better args = programName + QLatin1Char(' '); } for (int i=0; i<arguments.size(); ++i) { QString tmp = arguments.at(i); // Quotes are escaped and their preceding backslashes are doubled. tmp.replace(QRegExp(QLatin1String("(\\\\*)\"")), QLatin1String("\\1\\1\\\"")); if (tmp.isEmpty() || tmp.contains(QLatin1Char(' ')) || tmp.contains(QLatin1Char('\t'))) { // The argument must not end with a \ since this would be interpreted // as escaping the quote -- rather put the \ behind the quote: e.g. // rather use "foo"\ than "foo\" int i = tmp.length(); while (i > 0 && tmp.at(i - 1) == QLatin1Char('\\')) --i; tmp.insert(i, QLatin1Char('"')); tmp.prepend(QLatin1Char('"')); } args += QLatin1Char(' ') + tmp; } return args;
}
// Use ShellExecuteEx() to trigger an UAC prompt when CreateProcess()fails
// with ERROR_ELEVATION_REQUIRED.
static bool startDetachedUacPrompt(const QString &programIn, const QStringList &arguments,
const QString &workingDir, qint64 *pid)
{
typedef BOOL (WINAPI *ShellExecuteExType)(SHELLEXECUTEINFOW *);static const ShellExecuteExType shellExecuteEx = // XP ServicePack 1 onwards. reinterpret_cast<ShellExecuteExType>(QSystemLibrary::resolve(QLatin1String("shell32"), "ShellExecuteExW")); if (!shellExecuteEx) return false; const QString args = qt_create_commandline(QString(), arguments); // needs arguments only SHELLEXECUTEINFOW shellExecuteExInfo; memset(&shellExecuteExInfo, 0, sizeof(SHELLEXECUTEINFOW)); shellExecuteExInfo.cbSize = sizeof(SHELLEXECUTEINFOW); shellExecuteExInfo.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_UNICODE | SEE_MASK_FLAG_NO_UI; shellExecuteExInfo.lpVerb = L"runas"; const QString program = QDir::toNativeSeparators(programIn); shellExecuteExInfo.lpFile = reinterpret_cast<LPCWSTR>(program.utf16()); if (!args.isEmpty()) shellExecuteExInfo.lpParameters = reinterpret_cast<LPCWSTR>(args.utf16()); if (!workingDir.isEmpty()) shellExecuteExInfo.lpDirectory = reinterpret_cast<LPCWSTR>(workingDir.utf16()); shellExecuteExInfo.nShow = SW_SHOWNORMAL; if (!shellExecuteEx(&shellExecuteExInfo)) return false; if (pid) *pid = qint64(GetProcessId(shellExecuteExInfo.hProcess)); CloseHandle(shellExecuteExInfo.hProcess); return true;
}
bool startDetached(const QString &program, const QStringList &arguments, const QString &workingDir, qint64 *pid)
{
static const DWORD errorElevationRequired = 740;QString args = qt_create_commandline(program, arguments); bool success = false; PROCESS_INFORMATION pinfo; DWORD dwCreationFlags = (GetConsoleWindow() ? 0 : CREATE_NO_WINDOW); dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT; dwCreationFlags |= DETACHED_PROCESS; STARTUPINFOW startupInfo = { sizeof( STARTUPINFO ), 0, 0, 0, (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; success = CreateProcess(0, (wchar_t*)args.utf16(), 0, 0, FALSE, dwCreationFlags, 0, workingDir.isEmpty() ? 0 : (wchar_t*)workingDir.utf16(), &startupInfo, &pinfo); if (success) { CloseHandle(pinfo.hThread); CloseHandle(pinfo.hProcess); if (pid) *pid = pinfo.dwProcessId; } else if (GetLastError() == errorElevationRequired) { success = startDetachedUacPrompt(program, arguments, workingDir, pid); } return success;
}
void BccMainWindow::on_pushButton_CreateP_clicked()
{
char cWindowsDirectory[MAX_PATH] = { 0 };//LPTSTR 与 wchar_t* 等价(Unicode环境下) LPTSTR cWinDir = new TCHAR[MAX_PATH]; memset(cWinDir, MAX_PATH, 0); //GetCurrentDirectory(MAX_PATH, cWinDir); wcscpy_s(cWinDir, MAX_PATH, L"D:\\Tool\\DevMng.exe"); LPTSTR sConLin = cWinDir; STARTUPINFO si; PROCESS_INFORMATION pi; ZeroMemory(&si, sizeof(si)); ZeroMemory(&pi, sizeof(pi)); //创建一个新进程 if (CreateProcess( NULL, // 指向一个NULL结尾的、用来指定可执行模块的宽字节字符串 sConLin, // 命令行字符串 NULL, // 指向一个SECURITY_ATTRIBUTES结构体,这个结构体决定是否返回的句柄可以被子进程继承。 NULL, // 如果lpProcessAttributes参数为空(NULL),那么句柄不能被继承。<同上> false,// 指示新进程是否从调用进程处继承了句柄。 0, // 指定附加的、用来控制优先类和进程的创建的标 // CREATE_NEW_CONSOLE 新控制台打开子进程 // CREATE_SUSPENDED 子进程创建后挂起,直到调用ResumeThread函数 NULL, // 指向一个新进程的环境块。如果此参数为空,新进程使用调用进程的环境 NULL, // 指定子进程的工作路径 &si, // 决定新进程的主窗体如何显示的STARTUPINFO结构体 &pi // 接收新进程的识别信息的PROCESS_INFORMATION结构体 )) { qDebug() << "create process success" << endl; //下面两行关闭句柄,解除本进程和新进程的关系,不然有可能不小心调用TerminateProcess函数关掉子进程 // CloseHandle(pi.hProcess); // CloseHandle(pi.hThread); } else { qDebug() << "failed to create process" << endl; } ::GetCurrentProcess(); Sleep(1000); //终止子进程 //TerminateProcess(pi.hProcess, 300); //终止本进程,状态码 //ExitProcess(1001); //return 0;
}
-
-
@legahero said in After testing under windows, it is found that QT program will kill the process created by CreateProcess when it exits again:
I hope that when the main process exits, it does not exit other processes it started
Then your other child process must be detached.
Anyway, I see that your code contains both
QProcess
andCreateProcess
. It doesn't make sense to mix both in the same application, so you should just choose one. (I think QProcess is a lot simpler to use)If you have further questions, please clean up and simplify your code.