Qt 运行一个实例进程

QLocalSocket + QLocalServer

逻辑:首先一个新的实例启动时,将尝试连接到同一个本地服务器,如果连接失败,则表示第一个实例进程,创建一个本地服务器;否则,拉起已打开的实例进程。

main.cpp

复制代码
#include <QApplication>
#include "main_windows.h"
#include "single_application.h"

//QT启动屏蔽cmd
#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")

int main(int argc, char* argv[])
{
    //QApplication a(argc, argv);
    SingleApplication singleApplication(argc, argv);
    if (!singleApplication.IsRunning())
    {
        MainWindow mainWindow;
        mainWindow.show();

        singleApplication.m_mainWindow = &mainWindow;
        return SingleApplication::exec();
    }

    return 0;
}

single_application.h

复制代码
//
// Created by zhe.xiao on 2024/3/1.
//

#pragma once

#include <QApplication>
#include <QWidget>
#include <QLocalServer>
#include <QLocalSocket>

class SingleApplication : public QApplication
{
Q_OBJECT
public:
    SingleApplication(int& argc, char* argv[]);

    //是否已有实例在运行
    bool IsRunning();

private:
    //初始化本地连接
    void InitLocalConnection();

    //创建服务端
    void CreateLocalServer();

    //激活窗口
    void ActivateWindow();

public:
    //MainWindow指针
    QWidget* m_mainWindow;

private:
    //运行状态
    bool m_isRunning;
    //是否已有实例在运行
    QLocalServer* m_localserver;
    //本地socket Server
    QString m_applicationName;
    //连接超时时间
    int m_timeout = 1000;

private slots:
    //有新连接时触发
    void OnNewConnection();
};

single_application.cpp

复制代码
//
// Created by zhe.xiao on 2024/3/1.
//

#include <QFileInfo>
#include "single_application.h"
#include <QDebug>

SingleApplication::SingleApplication(int& argc, char* argv[]) : QApplication(argc, argv)
{
    m_isRunning = false;
    m_mainWindow = nullptr;
    m_localserver = nullptr;
    m_applicationName = QFileInfo(QApplication::applicationFilePath()).fileName();

    qDebug() << "m_serverName:" << m_applicationName;

    InitLocalConnection();
}

/**
 * 通过socket通讯实现程序单实例运行,
 * 初始化本地连接,如果连接不上server,则创建,否则退出
 */
void SingleApplication::InitLocalConnection()
{
    m_isRunning = false;

    //尝试连接本地服务器,如果连上了就触发OnNewConnection,
    QLocalSocket socket;
    socket.connectToServer(m_applicationName);
    if (socket.waitForConnected(m_timeout))
    {
        m_isRunning = true;
        return;
    }

    //首次打开exe连接不上,则需要先创建一个本地服务器
    CreateLocalServer();
}

void SingleApplication::CreateLocalServer()
{
    m_localserver = new QLocalServer(this);
    connect(m_localserver, &QLocalServer::newConnection, this, &SingleApplication::OnNewConnection);
    if (!m_localserver->listen(m_applicationName))
    {
        // 此时监听失败,可能是程序崩溃时,残留进程服务导致的,移除
        if (m_localserver->serverError() == QAbstractSocket::AddressInUseError)
        {
            QLocalServer::removeServer(m_applicationName);
            m_localserver->listen(m_applicationName); //重新监听
        }
    }
}

/**
 * 通过socket通讯实现程序单实例运行,监听到新的连接【即重新双击exe】时触发该函数.
 */
void SingleApplication::OnNewConnection()
{
    QLocalSocket* localSocket = m_localserver->nextPendingConnection();
    if (localSocket)
    {
        localSocket->waitForReadyRead(m_timeout * 2);
        delete localSocket;

        //激活窗口
        ActivateWindow();
    }
}

void SingleApplication::ActivateWindow()
{
    if (m_mainWindow != nullptr)
    {
        m_mainWindow->raise();
        m_mainWindow->showNormal();
        m_mainWindow->activateWindow();
    }
}


bool SingleApplication::IsRunning()
{
    return m_isRunning;
}
相关推荐
vastsmile11 分钟前
(R)26.04.23 hermes agent执行本地命令超级慢的原因
开发语言·elasticsearch·r语言
我头发多我先学37 分钟前
C++ 模板全解:从泛型编程初阶到特化、分离编译进阶
java·开发语言·c++
YSF2017_31 小时前
C语言16-makefile(3)——makefile的模式规则
linux·c语言·开发语言
星星码️1 小时前
C++选择题练习(一)
开发语言·c++
herinspace2 小时前
管家婆实用贴-如何分离和附加数据库
开发语言·前端·javascript·数据库·语音识别
ILYT NCTR2 小时前
搭建Golang gRPC环境:protoc、protoc-gen-go 和 protoc-gen-go-grpc 工具安装教程
开发语言·后端·golang
小雅痞2 小时前
[Java][Leetcode simple] 28. 找出字符串中第一个匹配项的下标
java·开发语言·leetcode
likerhood2 小时前
java中的不可变类(Immutable)
java·开发语言
Ulyanov2 小时前
《PySide6 GUI开发指南:QML核心与实践》 第一篇:GUI新纪元——QML与PySide6生态系统全景
开发语言·python·qt·qml·雷达电子对抗
Rust研习社3 小时前
从入门到实践:Rust 异步编程完全指南
开发语言·后端·rust