qt防止程序多开,windows下测试有效

防多开类

通过内存映像与 socket通讯方式  判断应用是否运行,qt的方法,如果只是windows,可以用互斥,全局原子等方法

类原文地址:https://blog.csdn.net/sunflover454/article/details/50426639

#ifndef SINGLEAPPLICATION_H
#define SINGLEAPPLICATION_H
 
#include <QObject>
#include <QApplication>
 
class QWidget;
class QLocalServer;
 
class SingleApplication : public QApplication
{
    Q_OBJECT
public:
    SingleApplication(int &argc, char **argv);
    bool isRunning();               // 是否已经有实例在运行
    QWidget *mainWindow;            // MainWindow指针
 
private slots:
    // 有新连接时触发
    void newLocalConnection();
 
private:
    // 初始化本地连接
    void initLocalConnection();
    // 创建服务端
    void newLocalServer();
    bool bRunning;                  // 是否已经有实例在运行
    QLocalServer *localServer;      // 本地socket Server
    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(NULL)
    , mainWindow(NULL)
{
    // 取应用程序名作为LocalServer的名字
    serverName = QFileInfo(QCoreApplication::applicationFilePath()).fileName();
    //qDebug()<<serverName;
    initLocalConnection();
}
 
 
 
// 说明:
// 检查是否已經有一个实例在运行, true - 有实例运行, false - 没有实例运行
 
bool SingleApplication::isRunning()
{
    return bRunning;
}
 
 
// 说明:
// 通过socket通讯实现程序单实例运行,监听到新的连接时触发该函数
 
void SingleApplication::newLocalConnection()
{
    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();
    }
}
 
 
// 说明:
// 通过socket通讯实现程序单实例运行,
// 初始化本地连接,如果连接不上server,则创建,否则退出
 
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();
}
 
 
// 说明:
// 创建LocalServer
 
void SingleApplication::newLocalServer()
{
    localServer = new QLocalServer(this);
    connect(localServer, SIGNAL(newConnection()), this, SLOT(newLocalConnection()));
    if(!localServer->listen(serverName))
    {
        // 此时监听失败,可能是程序崩溃时,残留进程服务导致的,移除之
        if(localServer->serverError() == QAbstractSocket::AddressInUseError)
        {
            QLocalServer::removeServer(serverName); // <-- 重点
            localServer->listen(serverName); // 再次监听
        }
    }
}

使用

#include "usbtest.h"
#include <QtWidgets/QApplication>
#include "SingleApplication.h"

int main(int argc, char *argv[])
{
   //QApplication a(argc, argv);
   // usbtest w;
   // w.show();
   // return a.exec();


	//单实例进程,或者说防止程序多开
	SingleApplication a(argc, argv);

	if (!a.isRunning())
	{
		usbtest	w;	//传入一个要激活程序的窗口,当多开时会激活已有进程的窗口,且多开失败
		a.mainWindow = &w;
		w.show();

		return a.exec();
	}
	return 0;

}

猜你喜欢

转载自blog.csdn.net/y281252548/article/details/113991896