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

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

1 需求背景


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


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


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


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


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


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

目录
相关文章
|
5月前
|
Linux iOS开发 开发者
Qt问题(二):无法定位程序输入点于动态链接库
动态链接库(Dynamic Link Library,简称DLL)是一种可执行文件格式,常见于Windows操作系统中,而在Linux和macOS等其他操作系统中,相似的概念通常被称为共享库(Shared Library)。动态链接库允许程序在运行时加载所需的代码和数据,而不是在编译时静态链接到应用程序中。这种方式带来了几个重要的优点:
518 3
|
5月前
|
Linux 开发者 iOS开发
QT:基于QMediaPlayer制作的视频播放器(最下方有整合包,可直接运行)
QMediaPlayer是Qt多媒体模块中的一个核心类,它提供了播放音频和视频内容的功能。这个类的设计旨在简化跨平台的媒体播放,使得开发者能够在多种操作系统(如Linux、Windows、macOS及移动平台)上轻松集成多媒体播放能力到他们的应用中,而无需关心底层实现细节。以下是关于QMediaPlayer的一些关键点:
614 1
|
3月前
|
C语言 Android开发 C++
基于MTuner软件进行qt的mingw编译程序的内存泄漏检测
本文介绍了使用MTuner软件进行Qt MinGW编译程序的内存泄漏检测的方法,提供了MTuner的下载链接和测试代码示例,并通过将Debug程序拖入MTuner来定位内存泄漏问题。
基于MTuner软件进行qt的mingw编译程序的内存泄漏检测
|
7月前
|
开发框架 自然语言处理 Linux
Qt:构建强大跨平台应用程序的框架
Qt:构建强大跨平台应用程序的框架
|
5月前
|
调度
【浅入浅出】Qt多线程机制解析:提升程序响应性与并发处理能力
在学习QT线程的时候我们首先要知道的是QT的主线程,也叫GUI线程,意如其名,也就是我们程序的最主要的一个线程,主要负责初始化界面并监听事件循环,并根据事件处理做出界面上的反馈。但是当我们只限于在一个主线程上书写逻辑时碰到了需要一直等待的事件该怎么办?它的加载必定会带着主界面的卡顿,这时候我们就要去使用多线程。
176 6
|
5月前
|
Linux 开发者 iOS开发
QT:基于QMediaPlayer制作的视频播放器(最下方有整合包,可直接运行)
QMediaPlayer是Qt多媒体模块中的一个核心类,它提供了播放音频和视频内容的功能。这个类的设计旨在简化跨平台的媒体播放,使得开发者能够在多种操作系统(如Linux、Windows、macOS及移动平台)上轻松集成多媒体播放能力到他们的应用中,而无需关心底层实现细节。以下是关于QMediaPlayer的一些关键点:
152 0
|
6月前
Qt MainWindow 程序主窗口
Qt MainWindow 程序主窗口
|
7月前
|
人工智能 编译器 C++
新版Qt6快速打包程序脚本
不知道啥时候Qt更新了,目前是6.7.0,项目默认的生成路径改了, 从 项目目录的同级目录 改为了 项目目录中的build目录, 之前的脚本也用不了了,所以用AI更新了一下脚本, 希望能帮到大家,方便快速打包程序到桌面。
174 9