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