Qt外部调用进程类QProcess的使用

news2024/11/17 23:42:17

有的时候我们需要在自己程序运行过程中调用其他进程,那么就需要用到QProcess。

首先可以了解一些关于进程的相关知识:线程与进程,你真得理解了吗_进程和线程的区别-CSDN博客

进程是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配的基本单位,是操作系统结构的基础。 

如何查看系统中正在运行的进程以及如何杀死进程:

Windows:

启动进程:tasklist

杀死进程:taskkill /F /PID 4204(进程id) 

 

Linux:

查看进程:ps -ef

杀死进程:kill -9 4341(进程id)

 QProces的使用:

QProcess通过start和startDetached两个方法都可以启动进程,其中前者是一体式启动,即外部程序启动后,将随主程序的退出而退出。后者是分离式启动,即外部程序启动后,当主程序退出时并不退出,而是继续运行。

这次主要说start这个方法:
void 
start(const QString &program, const QStringList &arguments, QIODevice::OpenMode mode = ReadWrite) 

主要需要注意第一个参数和第二个参数,第一个参数是要执行的命令或者程序,第二个参数是这个程序的运行参数。关于这两个先看一个最简单的qt程序代码:

#include <QCoreApplication>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    return a.exec();
}

这个代码大家再熟悉不过来,就是一个最简单的qt控制台程序,不知道大家有没有注意过main函数的两个参数argc和argv[]。

  1. int argc:代表命令行参数的数量,即传递给程序的参数个数。通常情况下,argc至少为1,因为第一个参数通常是程序本身的名称。

  2. char *argv[]:是一个指向字符指针数组的指针,其中每个元素是一个指向表示一个命令行参数的C风格字符串的指针。argv[0]通常是程序的名称,后续元素是传递给程序的其他参数。

试着打印一下:

#include <QCoreApplication>
#include <QDebug>
int main(int argc, char *argv[]) {
  QCoreApplication a(argc, argv);
  for (int i = 0; i < argc; ++i) {
    qDebug() << argv[i];
  }
  return a.exec();
}

编译运行查看打印:

打印了一个参数,即程序的名称。试着给这个控制台程序启动时加几个参数:

 

使用QtCreator传入运行参数也可以这样设置:

 

 运行查看结果:

 也可以使用QCoreApplication::arguments()打印参数:

#include <QCoreApplication>
#include <QDebug>
int main(int argc, char *argv[]) {
  QCoreApplication a(argc, argv);
  for (int i = 0; i < argc; ++i) {
    qDebug() << argv[i];
  }
  QStringList args = QCoreApplication::arguments();
  for (const QString &arg : args) {
    qDebug() << arg;
  }
  return a.exec();
}

编译运行查看:

QProcess使用start传入对应参数,这是要启动的程序:

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent), ui(new Ui::MainWindow) {
  ui->setupUi(this);
  for (const QString &arg : QCoreApplication::arguments()) {
    ui->textEdit->append(arg);
  }
}

MainWindow::~MainWindow() { delete ui; }

将程序参数显示到对应QTextEdit上:

#include <QCoreApplication>
#include <QDebug>
#include <QProcess>
int main(int argc, char *argv[]) {
  QCoreApplication a(argc, argv);
  QProcess *p = new QProcess;
  QStringList args;
  args << "1"
       << "2"
       << "3";
  p->start("G:\\qtprojects\\ConsoleP\\debug\\ConsoleP.exe", args);
  return a.exec();
}

编译查看运行结果:

QProcess通过processId来获取对应进程id。 

关于QProcess的信号:

 其中readyReadStandardError()与readyReadStandardOutput()收到对应信号后通过readAllStandardOutput()与readAllStandardError()来获取对应程序标准输出以及异常输出,进程运行完成后会触发finished()信号,进程状态改变会触发stateChanged信号。写一个例子:

头文件:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE

class QProcess;
class MainWindow : public QMainWindow {
    Q_OBJECT

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

private:
    void appendLog(const QString &text);

private slots:
    void on_open_clicked();

    void on_cmd_clicked();

    void on_clear_clicked();

private:
    Ui::MainWindow *ui;
    QProcess *m_Process;
};
#endif // MAINWINDOW_H

源文件:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDateTime>
#include <QFileDialog>
#include <QProcess>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent), ui(new Ui::MainWindow) {
    ui->setupUi(this);
    m_Process = new QProcess;
    connect(m_Process, &QProcess::readyReadStandardOutput, [=]() {
        QByteArray output = m_Process->readAllStandardOutput();
        QString outputString = QString::fromLocal8Bit(output);
        appendLog("output:" + outputString);
    });
    connect(m_Process, &QProcess::readyReadStandardError, [=]() {
        QByteArray output = m_Process->readAllStandardError();
        QString outputString = QString::fromLocal8Bit(output);
        appendLog("error:" + outputString);
    });
    connect(m_Process, &QProcess::stateChanged,
            [=](QProcess::ProcessState newState) {
                appendLog("stateChanged:" + QString::number(newState));
            });
    connect(m_Process, &QProcess::errorOccurred,
            [=](QProcess::ProcessError error) {
                appendLog("errorOccurred:" + QString::number(error));
            });
    connect(m_Process,
            static_cast<void (QProcess::*)(int exitCode,
                                           QProcess::ExitStatus exitStatus)>(
                &QProcess::finished),
            [=](int exitCode, QProcess::ExitStatus exitStatus) {
                appendLog("finished:" + QString::number(exitCode) + ":" +
                          QString::number(exitStatus));
            });
}

MainWindow::~MainWindow() {
    delete ui;
}

void MainWindow::appendLog(const QString &text) {
    ui->textEdit->append(QString("%1:program=%2:pid=%3:%4")
                             .arg(QDateTime::currentDateTime().toString(
                                 "yyyy/MM/dd hh:mm:ss.zzz"))
                             .arg(m_Process->program())
                             .arg(m_Process->processId())
                             .arg(text));
}

void MainWindow::on_open_clicked() {
    QString pragramName =
        QFileDialog::getOpenFileName(nullptr, nullptr, QString());
    ui->program->setText(pragramName);
}

void MainWindow::on_cmd_clicked() {
    if (ui->program->text().isEmpty()) return;
    m_Process->setProgram(ui->program->text());
    QStringList arguments;
    arguments << ui->arguments->text();
    m_Process->setArguments(arguments);
    m_Process->start();
}

void MainWindow::on_clear_clicked() {
    ui->textEdit->clear();
}

ui:

编译运行然后再对应输入框输入程序路径以及对应参数,以刚刚写的例子为例:

 然后关闭启动的进程:

可以看到关闭后触发了对应finished()信号,然后通过打印可以看到状态从打开到关闭的变化情况是:1(Starting)->2(Running)->0(NotRunning) 。并且触发finished()信号时由于进程已经关闭,所以获取不到对应的进程id,但是stateChanged(NotRunning)会先于finished(),并且这时进程没有完全关闭所有能获取到对应进程id。也可以输入一些cmd命令:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1485361.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

7.1.1 selenium介绍及安装chromedriver

目录 1. Selenium的用途 2. 安装Selenium库 3. 安装chromedriver 1. 查看谷歌版本号​编辑 2. 找到最新版本及下载 3. 配置环境变量 4. 检测是否配置成功 5. 用python初始化浏览器对象检测&#xff1a; 6. 参考链接 1. Selenium的用途 在前面我们提到&#xff1a;在我…

NIO核心三:Selector

一、基本概念 选择器提供一种选择执行已经就绪的任务的能力。selector选择器可以让单线程处理多个通道。如果程序打开了多个连接通道&#xff0c;每个连接的流量都比较低&#xff0c;可以使用Selector对通道进行管理。 二、如何创建选择器 1.创建Selector Selector select…

ArduinoTFTLCD应用

ArduinoTFTLCD应用 ArduinoTFTLCD应用硬件连接软件导入库显示数字、字符显示汉字方案1方案2 显示图片 总结 ArduinoTFTLCD应用 对于手工喜欢DIY的人来说&#xff0c;Arduino驱动的TFTLCD被很多人使用&#xff0c;此处就总结一下&#xff0c;使用的是VScode的PlatformIO插件驱动…

Docusaurus框架——react+antd+echarts自定义mdx生成图表代码解释文档

文章目录 ⭐前言⭐Docusaurus框架渲染mdx内容&#x1f496; 创建一个mdx文件&#x1f496; 创建一个react jsx文件&#x1f496; mdx引入react的组件并渲染&#x1f496; mdx引入react的组件源代码内容 ⭐渲染一个echarts地图的代码解释文档&#x1f496; echarts 渲染地图&…

USLE模型-P因子的计算

首先需要下载土地利用类型数据集&#xff0c;查看我的相关文章 对于已有的10种土地类型代码&#xff0c;需要按水土保持措施P值表进行重分类。 10是耕地&#xff0c;且庆阳市坡度10-15度左右&#xff0c;所以赋给了3&#xff08;最好再下个DEM计算一下&#xff0c;这里就统一用…

WebServer -- 注册登录

目录 &#x1f349;整体内容 &#x1f33c;流程图 &#x1f382;载入数据库表 提取用户名和密码 &#x1f6a9;同步线程登录注册 补充解释 代码 &#x1f618;页面跳转 补充解释 代码 &#x1f349;整体内容 概述 TinyWebServer 中&#xff0c;使用数据库连接池实现…

C++指针(三)

个人主页:PingdiGuo_guo 收录专栏&#xff1a;C干货专栏 文章目录 前言 1.字符指针 1.1字符指针的概念 1.2字符指针的用处 1.3字符指针的操作 1.3.1定义 1.3.2初始化 1.4字符指针使用注意事项 2.数组参数&#xff0c;指针参数 2.1数组参数 2.1.1数组参数的概念 2.1…

NCT 全国青少年编程图形化编程(Scratch)等级考试(一级)模拟测试H

202312 青少年软件编程等级考试Scratch一级真题 第 1 题 【 单选题 】 以下说法合理的是( ) A :随意点开不明来源的邮件 B :把密码设置成 abc123 C :在虚拟社区上可以辱骂他人 D :在改编他人的作品前&#xff0c; 先征得他人同意 正确答案&#xff1a; D 试题解析&…

python模块和包概念与使用

python模块和包概念与使用 Python模块与包的关键概念 在Python编程中&#xff0c;模块和包是代码组织和管理的基石。以下是关于Python模块与包的核心要点&#xff1a; 模块&#xff1a; 模块是一个包含Python代码的.py文件&#xff0c;它可以定义函数、类、变量等。通过导入模…

水经微图Web版1.6.0发布

让每一个人都有自己的地图&#xff01; 水经微图&#xff08;简称“微图”&#xff09;新版已上线&#xff0c;在该版本中主要新增了点线面图层分组样式设置、图层排序并按序绘制、KML支持矢量符号的存储、KML支持态势标绘要素存储和新增历史地图文本样式等。 现在&#xff0…

Leetcoder Day27| 贪心算法part01

语言&#xff1a;Java/Go 理论 贪心的本质是选择每一阶段的局部最优&#xff0c;从而达到全局最优。 什么时候用贪心&#xff1f;可以用局部最优退出全局最优&#xff0c;并且想不到反例到情况 贪心的一般解题步骤 将问题分解为若干个子问题找出适合的贪心策略求解每一个子…

使用plasmo框架开发浏览器插件,注入contents脚本和给页面添加UI组件

plasmo&#xff1a;GitHub - PlasmoHQ/plasmo: &#x1f9e9; The Browser Extension Framework plasmo是一个开发浏览器插件的框架&#xff0c;支持使用react和vue等技术&#xff0c;而且不用手动管理manifest.json文件&#xff0c;框架会根据你在框架中的使用&#xff0c;自…

美团分布式 ID 框架 Leaf 介绍和使用

一、Leaf 在当今日益数字化的世界里&#xff0c;软件系统的开发已经成为了几乎所有行业的核心。然而&#xff0c;随着应用程序的规模不断扩大&#xff0c;以及对性能和可扩展性的需求不断增加&#xff0c;传统的软件架构和设计模式也在不断地面临挑战。其中一个主要挑战就是如…

SAP EC-CS如何实现自动抵消

SAP EC-CS 是SAP 比较早的合并方案&#xff0c;尽管后面有很多其他的方案作为替代&#xff0c;但 EC-CS 因为其成熟性&#xff0c;在集团合并单元不多的情况下&#xff0c;也可以作为一个不错的合并解决方案。可以说&#xff0c;会计报表合并一个核心就是实现抵消的处理&#x…

nginx------------缓存功能 ip透传 负载均衡 (六)

一、http 协议反向代理 &#xff08;一&#xff09;反向代理示例:缓存功能 缓存功能可以加速访问&#xff0c;如果没有缓存关闭后端服务器后&#xff0c;图片将无法访问&#xff0c;缓存功能默认关闭&#xff0c;需要开启。 ​ proxy_cache zone_name | off; 默认off #指明调…

2024全新手机软件下载应用排行、平台和最新发布网站,采用响应式织梦模板

这是一款简洁蓝色的手机软件下载应用排行、平台和最新发布网站&#xff0c;采用响应式织梦模板。 主要包括主页、APP列表页、APP详情介绍页、新闻资讯列表、新闻详情页、关于我们等模块页面。 地 址 &#xff1a; runruncode.com/php/19703.html 软件程序演示图&#xff1a;…

C语言中的字符魔法:大小写转换的艺术

引言 在C语言的世界里&#xff0c;字符处理是一项基础且重要的任务。字符作为编程中最基本的元素之一&#xff0c;承担着信息展示、数据交互等多重角色。特别是在处理文本信息时&#xff0c;字符的转换和识别显得尤为重要。大小写字母的转换就是其中一个常见的需求&#xff0c…

串及BF朴素查找算法(学习整理):

关于串的相关定义&#xff1a; 串&#xff1a;用‘ ’表示的字符序列空串&#xff1a;包含零个字符的串子串&#xff1a;包含传本身和空串的子串 eg: abc(,a,b,c,ab,bc,ac,abc)共7个&#xff1a;串的长度的阶乘1&#xff08;空串&#xff09;真子串&#xff1a;不包含自身的所…

linux安装matlab获取许可证

1.点击许可证 2. 3. 4. 4.主机ID 打开linux输入 /sbin/ifconfigether后边的就是 6.计算机登录名 打开linux输入 whoami7. 8. 9.

【已亲测有效】如何彻底删除nodejs,避免影响安装新版本

第一步开始菜单搜索uninstall node.js&#xff0c;点击之后等待删除&#xff08;删除node_modules文件夹以及以下这些文件&#xff09; 第二步手动删除nodejs下载位置的其他文件夹。&#xff08;就是另外自己新建的两个文件夹node_cache和node_global&#xff09; 到这里其实应…