(十六)QT启动外部程序和URL

在工作中会遇到一种情况,启动外部程序,例如你需要客户打开浏览器或者你的工程和其他程序是联动的等等。QT提供了QProcess类来启动外部程序,启动外部程序。

一、启动外部程序的方式

1.startDetached()
通常情况下,我们启动程序后就不会再次关注该程序,那么我们就可以使用startDetached()方法,它有一个bool的返回值,简单的告诉你程序是否启动了。并且即使我们的程序关闭了,我们打开的程序也不会关闭,依然保持自己的状态(也就是不论它是关闭、崩溃、打开中,都和我们的程序无关)

bool startDetached(qint64 *pid = nullptr);
static bool startDetached(const QString &program, const QStringList &arguments,
                              const QString &workingDirectory, qint64 *pid = nullptr);
static bool startDetached(const QString &program, const QStringList &arguments);
static bool startDetached(const QString &command);

需要注意的是你要传入的路径需要是exe的绝对路径,否则QT是找不到exe的所在位置的:

bool test = process->startDetached("D:\\software\\Notepad++\\notepad++.exe");
qDebug() << "test : "<< test;

根据返回值,我们可以知道程序是否启动成功。
好处如下:
1)有返回值,我们可以知道程序是否启动成功
2)即使我们的程序关闭了,我们打开的程序也不会关闭,依然保持自己的状态
3)可以多次打开同一个外部程序(每次打开的进程号PID都不一样)

2.start()
如果你想让一个外部程序随着你的程序的关闭而关闭,可以使用start()方式。具体如下:

QProcess *process;
process->start("D:\\software\\Notepad++\\notepad++.exe");

这里有一个需要注意的点:
process不能是局部变量,除非你的函数始终运行,否则process会被析构,那么很容易出现异常,例如:

void MainWindow::startProject()
{
    QProcess *process = new QProcess;
    process->start("D:\\software\\Notepad++\\notepad++.exe");
}

这种写法,会报“Destroyed while process (“D:\software\Notepad++\notepad++.exe”) is still running.”错误。启动后process就非常容易被析构,导致外部程序无法运行。
所以最好的办法是把process建为全局变量,最后在自己程序析构的时候,析构process。
好处:
1)外部程序随着你的程序的关闭而关闭

二、外部程序的路径带有空格

这两个都可以打开外部程序,但是我们经常会遇到一个问题:外部程序的路径带有空格,导致程序无法打开,我们可以这样操作:

process->start("C:\\Program Files (x86)\\TeamViewer\\TeamViewer.exe",QStringList("C:\\Program Files (x86)\\TeamViewer\\TeamViewer.exe"));
bool test = process->startDetached("C:\\Program Files (x86)\\TeamViewer\\TeamViewer.exe",QStringList("C:\\Program Files (x86)\\TeamViewer\\TeamViewer.exe"));

也就是使用了参数的方式,实际上const QStringList &arguments是参数,调用外部程序exe传入的参数,QT实际调用的是Windows的一个API,叫做CommandLineToArgvW(),这个API会解析你传入的参数列表arguments,arguments的第一个参数会被当成程序的路径解析。这就是为什么带有空格的路径可以启动的原因,Windows支持带有空格的路径启动程序。

三、等待外部程序启动

如果我们用start()的方式启动外部程序,特别是在实际情况下,QT有多个信号工作在处理,你想让外部程序先启动,然后再执行接下来的动作。但是有时你会发现,明明是先启动的外部程序,为啥我接下来的动作会先启动呢?
这就要说到start()的工作方式。start()是异步的,虽然你调用QProcess以后,QProcess会立刻进入启动中状态,即starting状态,如果QProcess启动成功,它才会发送started()信号,启动完成;否则会发送 errorOccurred()信号,报错!
既然都是信号,按照QT的信号槽工作机制,有其他信号插入进来也无可厚非。遇到这种问题,我们需要使用waitForFinished(),等待命令执行完毕。如下:

    process->start("C:\\Program Files (x86)\\TeamViewer\\TeamViewer.exe");
    bool test = process->waitForStarted();
    if(!test)
    {
        QProcess::ProcessError result = process->error();
        qDebug() << "result : "<< result;
    }

结果如下:
在这里插入图片描述
QT提供了几种比较简单的错误码,如下:

    enum ProcessError {
        FailedToStart, //### file not found, resource error
        Crashed,
        Timedout,
        ReadError,
        WriteError,
        UnknownError
    };

你可以由此初步判断程序哪里出现了异常。

四、只启动一个外部程序

如果你只想启动一个外部程序呢,或者你想知道这个外部程序是否已经启动,如果启动了,你就不需要再启动了。我们可以查看Windows的任务列表,在任务列表中找是不是有这个外部程序,如果没有再启动外部程序。这里就用到了tasklist命令,它会把Windows的任务列表打印出来。我们在返回的数据中找是不是有外部程序的名称即可。(注意有的外部程序展示名和启动名大小写可能不一样,注意分辨)

    QProcess process1;
    process1.start("tasklist");
    process1.waitForFinished(); //等待命令执行结束
    QByteArray result = process1.readAllStandardOutput();

    qDebug() << result;

    if(-1==result.indexOf("TeamViewer.exe"))
    {
        startProject();
    }
    else
    {
        qDebug() << "TeamViewer have already started";
    }

void MainWindow::startProject()
{
    process->start("C:\\Program Files (x86)\\TeamViewer\\TeamViewer.exe",QStringList("C:\\Program Files    (x86)\\TeamViewer\\TeamViewer.exe"));
    bool test = process->waitForStarted();
    if(!test)
    {
        QProcess::ProcessError result = process->error();
        qDebug() << "result : "<< result;
    }
}

结果如下:
在这里插入图片描述

五、启动一个URL

启动一个URL很简单,例如:

#include <QDesktopServices>
#include <QUrl>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    QDesktopServices::openUrl(QUrl(QLatin1String("https://www.baidu.com")));
    QDesktopServices::openUrl(QUrl(QLatin1String("file:C:\\Program Files (x86)")));
}

openUrl是一个静态函数,可以直接调用,不仅可以打开浏览器URL,还可以打开本地电脑上的路径URL。
需要注意的是:openUrl调用的是客户电脑上的默认浏览器,如果客户电脑上未设置默认浏览器,是无法打开的(没有任何反应)
同时这个函数只返回true(打开成功)、false(打开失败,包含打开浏览器失败、未设置默认浏览器、打开URL失败等,QT不区分这些错误),所以接受这个返回值的结果未false需要多注意提醒,否则客户是不知道如何处理的

额外注意:openUrl是QT的接口(QDesktopServices类中),openUrlExternally()是QML中的接口,quick和quick2调用,不要搞混了

  • 5
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值