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

举报
DreamLife 发表于 2022/04/15 22:31:14 2022/04/15
【摘要】 欢迎来到我的博客,希望这篇文章对你有所帮助,如果觉得不错,请点赞搜藏哈。 1 需求背景 还是原来的网络关机助手项目“PowerControl”,目前他有了一个新的运行环境,就是在我们的某个带有电脑...

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();// 临界区 

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

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


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

原文件代码

#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);
        }
    }

}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73

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;
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

2.3使用官方的QSignalApplication

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


博客签名2021

文章来源: dreamlife.blog.csdn.net,作者:DreamLife.,版权归原作者所有,如需转载,请联系作者。

原文链接:dreamlife.blog.csdn.net/article/details/115528103

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。