发布
社区首页 >问答首页 >QProcess为什么无法使用terminate方法结束进程?

QProcess为什么无法使用terminate方法结束进程?

提问于 2025-01-15 11:43:57
回答 0关注 0查看 31

在学习QThread和QProcess的时候,想做一个类似多线程进程监测的工具,写demo的时候遇到了几个问题,网上搜索到的方法均无法解决,望大佬答疑

问题:程序能够正常启动我想启动的程序(例如cmd.exe),但是在点击停止时会出现无法终止程序的情况,会报错如下信息,或者直接导致程序崩溃

代码语言:txt
复制
QProcess: Destroyed while process ("cmd.exe") is still running.
QWinEventNotifier: Event notifiers cannot be enabled or disabled from another thread

输出QProcess拉起的进程ID后,使用taskkill也是需要/f参数才能够正常终止,否则也会报错

代码语言:txt
复制
错误: 无法终止 PID 为 18668 的进程。
原因: 只能强行终止这个进程(带 /F 选项)。

下方是我的代码

程序界面及组件名称

程序界面及组件
程序界面及组件

main.cpp

代码语言:cpp
代码运行次数:0
复制
#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

mainwindow.h

代码语言:cpp
代码运行次数:0
复制
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

#include "processmonitor.h"

QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
    ProcessMonitor *pm;

    void setupConnection();

private slots:
    void handleReadyReadStandardOutput(const QString& data);
    void handleReadyReadStandardError(const QString& data);
    void handleStarted(const QString& message);
    void handleStateChanged(QProcess::ProcessState newState);
    void handleStopped(const QString& message);

    void on_start_process_clicked();
    void on_stop_process_clicked();
};
#endif // MAINWINDOW_H

mainwindow.cpp

代码语言:cpp
代码运行次数:0
复制
#include "mainwindow.h"
#include "./ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent), pm(new ProcessMonitor)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    if(!pm) {
        qDebug() << "ProcessMonitor Start Failed,Exit!";
        QApplication::quit();
    }
    setupConnection();

}

MainWindow::~MainWindow()
{
    if(pm) {
        pm->stopProcess();
        delete pm;
    }
    delete ui;
}

void MainWindow::setupConnection() {
    connect(pm, &ProcessMonitor::readyReadStandardOutput, this, &MainWindow::handleReadyReadStandardOutput);
    connect(pm, &ProcessMonitor::readyReadStandardError, this, &MainWindow::handleReadyReadStandardError);
    connect(pm, &ProcessMonitor::started, this, &MainWindow::handleStarted);
    connect(pm, &ProcessMonitor::stateChanged, this, &MainWindow::handleStateChanged);
    connect(pm, &ProcessMonitor::stopped, this, &MainWindow::handleStopped);
}

void MainWindow::handleReadyReadStandardOutput(const QString& data){
    this->ui->outInfo->appendPlainText(data);
}

void MainWindow::handleReadyReadStandardError(const QString& data){
    this->ui->outInfo->appendPlainText("Error:" + data );
}

void MainWindow::handleStarted(const QString& message){
    this->ui->selfInfo->appendPlainText(message);
}

void MainWindow::handleStateChanged(QProcess::ProcessState newState) {
    QString stateString;
    switch(newState) {
    case QProcess::NotRunning:
        stateString = "Not Running";
        break;
    case QProcess::Starting:
        stateString = "Starting";
        break;
    case QProcess::Running:
        stateString = "Running";
        break;
    default:
        stateString = "Unknown State";
        break;
    }
    this->ui->selfInfo->appendPlainText("State Changed: " + stateString);
}


void MainWindow::handleStopped(const QString& message){
    this->ui->selfInfo->appendPlainText(message);
}

void MainWindow::on_start_process_clicked()
{
    this->pm->start();
}

void MainWindow::on_stop_process_clicked()
{
    this->pm->stopProcess();
}

processmonitor.h

代码语言:cpp
代码运行次数:0
复制
#ifndef PROCESSMONITOR_H
#define PROCESSMONITOR_H

#include <QThread>
#include <QProcess>
#include <QDebug>

class ProcessMonitor : public QThread
{
    Q_OBJECT
public:
    ProcessMonitor();
    ~ProcessMonitor();

    void run() override;
    void stopProcess();

signals:
    void readyReadStandardOutput(QString output);
    void readyReadStandardError(QString error);
    void started(QString message);
    void stateChanged(QProcess::ProcessState newState);
    void stopped(QString message);

private:
    QProcess *process;

private slots:
    void handleReadyReadStandardOutput();
    void handleReadyReadStandardError();
    void handleStarted();
    void handleStateChanged(QProcess::ProcessState newState);
};

#endif // PROCESSMONITOR_H

processmonitor.cpp

代码语言:cpp
代码运行次数:0
复制
#include "processmonitor.h"

ProcessMonitor::ProcessMonitor()
    : process(nullptr)
{
}

ProcessMonitor::~ProcessMonitor() {
    stopProcess(); // 确保在销毁时停止进程
}

void ProcessMonitor::run() {
    if (this->process) {
        delete this->process;
    }
    this->process = new QProcess();
    if (!this->process) {
        qDebug() << "Error: unable to instantiate QProcess";
        return;
    }
    // this->process->setWorkingDirectory("E:\\test");

    connect(this->process, &QProcess::readyReadStandardOutput, this, &ProcessMonitor::handleReadyReadStandardOutput);
    connect(this->process, &QProcess::readyReadStandardError, this, &ProcessMonitor::handleReadyReadStandardError);  // 修正此处
    connect(this->process, &QProcess::started, this, &ProcessMonitor::handleStarted);
    connect(this->process, &QProcess::stateChanged, this, &ProcessMonitor::handleStateChanged);

    this->process->start("cmd.exe");
    qDebug() << "ProcessID:" << this->process->processId();
    this->exec();
}

void ProcessMonitor::stopProcess() {
    if (!this->process) {
        emit stopped("[ProcessMonitor] No Process Created");
        return;  // 直接返回
    }

    this->process->terminate();
    // this->process->kill();

    if (this->process->waitForFinished(3000)) {
        emit stopped("[ProcessMonitor] Process Stopped");
    } else {
        this->process->kill();
        emit stopped("[ProcessMonitor] Process terminated failed, Killing");
    }

    delete this->process;  // 安全检查后直接释放内存
    this->process = nullptr;  // 置空指针
    this->quit(); // 确保在退出前永远调用
}

void ProcessMonitor::handleReadyReadStandardOutput() {
    if (!this->process) return;
    QByteArray data = this->process->readAllStandardOutput();
    emit readyReadStandardOutput(QString::fromLocal8Bit(data));
}

void ProcessMonitor::handleReadyReadStandardError() {
    if (!this->process) return;
    QByteArray data = this->process->readAllStandardError();
    emit readyReadStandardError(QString::fromLocal8Bit(data));
}

void ProcessMonitor::handleStarted() {
    emit started("[ProcessMonitor] Process Started");
}

void ProcessMonitor::handleStateChanged(QProcess::ProcessState newState) {
    emit stateChanged(newState);
}

回答

和开发者交流更多问题细节吧,去 写回答
相关文章

相似问题

相关问答用户
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档