Qt6 防止程序多重启动,并实现双击图标显示已运行的程序

titlle bar

欢迎来到我的博客,希望这篇文章对你有所帮助,如果觉得不错,请点赞搜藏哈。

1 需求背景

还是原来的网络关机助手项目“PowerControl”,目前他有了一个新的运行环境,就是在我们的某个带有电脑的显示设备上面,可以理解为带有触摸功能的一体机,本来原生设计是无法触发这个需求的,但是由于信号的干扰没有很好的解决,导致整个屏幕下沉,屏幕的四周没法触摸,这就导致了Windows无法关机,也无法打开系统托盘。所以,关机就需要使用我的关机助手的界面来关机。

但是我的程序图标点击默认是启动程序,而我的程序有没有限制,而且默认还是最小化的,点再多也没有用,指示多开 了一堆程序而已。

所以本次需要增加以下功能

  1. 程序启动只能有一个进程,不能多开

  2. 双击桌面图标,如果程序启动,则显示程序,如果没有,则创建程序。

2 解决方案

要实现上面的功能,我先想到的就是寻找进程,程序启动的时候看看有没有这个的东西,但是呢,有没有搞过,这都21世纪了,百度一下,发现一个有很多种方法大致有一下几种

参考链接,这里只做搬运 https://blog.csdn.net/robertkun/article/details/8518576#

2.1共享内存

据说这种方法在Linux系统下会有一个内存释放的问题,在某种情况下会引起程序的异常或崩溃

核心代码如下

 // 确保只运行一次 
 
QSystemSemaphore sema("JAMKey",1,QSystemSemaphore::Open); 
sema.acquire();// 在临界区操作共享内存   SharedMemory 
 
QSharedMemory mem("SystemObject");// 全局对象名 
if (!mem.create(1))// 如果全局对象以存在则退出 
{ 
    QMessageBox::information(0, MESSAGEBOXTXT,"An instance has already been running.");
 
    sema.release();// 如果是 Unix 系统,会自动释放。 
 
    return 0; 
} 
 
sema.release();// 临界区 

2.2使用QLocalServer和QLocalSocker

这种也是我使用的版本,参考链接找不到,不过代码都是找搬过来的,连接:https://blog.csdn.net/sunflover454/article/details/50426639

头文件代码

#ifndef SINGLEAPPLICATION_H
#define SINGLEAPPLICATION_H

#include <QApplication>
#include <QObject>

class QWidget;
class QLocalServer;

class SingleApplication : public QApplication
{
    Q_OBJECT
public:
    SingleApplication(int &argc,char **argv);
    bool isRuning();
    QWidget *mainWindow;

private slots:
    void newLocalConnectioin();

private:
    void initLocalConnection();
    void newLocalServer();
    bool bRunning;
    QLocalServer *localServer;
    QString serverName;


};

#endif // SINGLEAPPLICATION_H

原文件代码

#include "singleapplication.h"
#include <QWidget>
#include <QtNetwork/QLocalSocket>
#include <QtNetwork/QLocalServer>
#include <QFileInfo>
#include <QLibrary>
SingleApplication::SingleApplication(int &argc, char **argv) :QApplication(argc,argv),bRunning(false),localServer(nullptr),mainWindow(nullptr)
{
    serverName = QFileInfo(QCoreApplication::applicationFilePath()).fileName();
    initLocalConnection();
}

bool SingleApplication::isRuning()
{
    return bRunning;
}

void SingleApplication::newLocalConnectioin()
{
    QLocalSocket *socket = localServer->nextPendingConnection();
    if(!socket)
        return;
    socket->waitForReadyRead(1000);
    QTextStream stream(socket);
    delete socket;
    if(mainWindow != NULL)
    {
        mainWindow->raise();
        mainWindow->activateWindow();
        mainWindow->setWindowState((mainWindow->windowState() & ~Qt::WindowMinimized) | Qt::WindowActive);
        mainWindow->show();
    }
}

void SingleApplication::initLocalConnection()
{
    bRunning = false;
    QLocalSocket socket;
    socket.connectToServer(serverName);
    if(socket.waitForConnected(500))
    {
        bRunning = true;
        QTextStream stream(&socket);
        QStringList args = QCoreApplication::arguments();

        if(args.count() > 1)
            stream << args.last();
        else
            stream << QString();
        stream.flush();
        socket.waitForBytesWritten();
        return;

    }
    newLocalServer();

}

void SingleApplication::newLocalServer()
{
    localServer = new QLocalServer(this);
    connect(localServer,SIGNAL(newConnection()),this,SLOT(newLocalConnectioin()));
    if(!localServer->listen(serverName))
    {
        if(localServer->serverError() == QAbstractSocket::AddressInUseError)
        {
            QLocalServer::removeServer(serverName);
            localServer->listen(serverName);
        }
    }

}

main 调用

#include "mainwindow.h"
#include <QApplication>
#include <singleapplication.h>
void autoStart()
{
    QString appName = QApplication::applicationName();
    QString appPath = QApplication::applicationFilePath();
    appPath = appPath.replace("/","\\");
    QSettings *reg=new QSettings("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",QSettings::NativeFormat);
    QString val = reg->value(appName).toString();
    if(val != appPath)
        reg->setValue(appName,appPath);
    reg->deleteLater();
}
//int main(int argc, char *argv[])
//{
//    QApplication a(argc, argv);
//    autoStart();
//    MainWindow w;
    w.show();
//    return a.exec();
//}


int main(int argc, char *argv[])
{
    SingleApplication a(argc, argv);
    if(!a.isRuning())
    {
        autoStart();
        MainWindow w;
        a.mainWindow = &w;
        //    w.show();
        return a.exec();
    }
    return 0;
}

2.3使用官方的QSignalApplication

官方类,但是默认不在Qt中,需要自己下载安装:参考链接https://blog.csdn.net/bloke_come/article/details/106319236


博客签名2021

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DreamLife.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值