QT检查是否有相同名称的进程在运行

这个功能一般是检查系统有没有已经在运行该软件,一般用于一个系统只需要启动一个这个软件就足够的情况下。没有多开程序的说法的情况下才会考虑该功能。

我这边主要是一个视觉匹配软件,需要调用系统的摄像头权限,并且整个软件的后台数据存储都是固定路径。多开该软件后必然会出现问题。而我自己有时候调试bug的时候也会无意中开了两个甚至三个软件,直到说摄像头打开失败我才发现打开了好几个软件。为了防止该软件在用户使用中出现问题。添加了这个功能。

之前在网上简单搜索一下,没有搜到很有效的内容。而且搜到的一些内容也需要重新理解里面的代码原理和执行方式,看了半天发现是其他功能,并不是我想要的东西。作为懒癌患者,还是自己动手造轮子吧。

大概思路就是通过程序里使用用户指令打开一个查看当前所有进程的方式来判断当前软件是否已经有正在运行。主要需要一个QProcess来运行指令。经过查询得知在Linux内用ps -A指令可以直接查看当前所有正在运行的进程,在windows上执行的程序则用 tasklist来查询。其主要代码已经被我封装在函数里,具体如下:

#include <QString>
#include <QProcess>
/***********************************************
 * 检查是否有相同的进程正在运行
 ***********************************************/
bool CheckRepeatProcess()
{
    QString input;
#if defined (Q_OS_LINUX)
    input = QString("ps -A");
#elif defined (Q_OS_WIN)
    input = QString("tasklist");
#else
    return false;
#endif
    QProcess *cmd = new QProcess();
    int nums = 0;
    cmd->start(input);
    QString processname = QString("processname");

    QString output;
    int findok;
    do
    {
        cmd->waitForReadyRead();
        output = QString::fromLocal8Bit(cmd->readAll());
        findok = output.indexOf(processname);
        if (findok >= 0)
        {
            nums++;
            output = output.mid(findok+1);
            findok = output.indexOf(processname);
            if (findok >= 0)
            {
                nums++;
            }
        }
    }
    while(!output.isEmpty());
    cmd->kill();
    delete cmd;
    cmd = nullptr;
    if (nums > 1)
    {
        return true;
    }
    return false;
}

注意程序中,用了一个while循环,主要是得到的数据可能比较多,发现只读取一次是不一定能读取完整,所以便添加while循环,什么时候读取的数据为空了,说明没有数据输出了,再退出while循环。而你当前程序的命名直接替换processname的内容就可以了。里面还有一个计数变量:nums,因为如果搜索到一次的话,这并不代表重复,计数最后为0次反而更有问题。因为你当前运行的程序也会在你搜索的程序中出现,所以按道理来说,出现次数大于一次便已经意味着重复运行了程序,这个时候再判定为有重复运行程序即可。

这个函数里,当代表能够正常运行的时候,返回true。当出现多个当前程序的时候,返回false。

最后顺便附上我在main函数调用此程序的代码:

#include <QMessageBox>
#include <QApplication>
//#include <QDebug>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    // 检查是否有相同的进程正在运行
    bool isOK = CheckRepeatProcess();  // 调用程序
    if (isOK)
    {
        QMessageBox m_r;
        m_r.setWindowTitle("提示");
        m_r.setText("程序已经在运行中,请勿重复打开该程序。");
        m_r.exec();
        return 0;
    }
    else
    {
        /* 
         * 在这里执行你的代码
         */
        return 0;
        
    }
}

发表评论