C++ Qt程序限制多开
代码
#include "mainwindow.h"#include <QApplication>
#include <QSharedMemory>
#include <QMessageBox>int main(int argc, char *argv[])
{QApplication a(argc, argv);// 使用 QSharedMemory 实现单实例(禁止多开)// 这个 key 要在全局范围内唯一,建议用“公司名_产品名_应用名”这样的格式QSharedMemory sharedMemory("MyCompany_MyProduct_UntitledApp_SingleInstance");// 尝试创建一段共享内存,如果失败,说明已经有实例创建过它了if (!sharedMemory.create(1)) {QMessageBox::warning(nullptr,QObject::tr("提示"),QObject::tr("程序已经在运行中,禁止多开。"));return 0; // 直接退出,不再创建主窗口}MainWindow w;w.show();return a.exec();
}
原理简要说明
QSharedMemory sharedMemory(“…”):
创建一段带有全局唯一 key 的共享内存对象,所有进程都能看到这个 key。
sharedMemory.create(1):
第一次运行时,这块共享内存还不存在,创建成功,返回 true,程序正常继续。
第二次运行时,这块共享内存已经被第一次运行的程序创建了,再调用 create 会失败,返回 false。
检测失败就弹框并 return 0:
表示已经有实例在运行,直接退出,不再执行后面的 MainWindow w; w.show();。
如果你希望修改提示文字或唯一 key,只需要改 QSharedMemory 里的字符串和 QMessageBox 的文案即可。
如果想在第二次运行时直接弹出第一次的窗口,可以使用下面的代码来实现:
#include "mainwindow.h"#include <QApplication>
#include <QLocalServer>
#include <QLocalSocket>int main(int argc, char *argv[])
{QApplication a(argc, argv);// 单实例 + 激活已存在窗口:使用 QLocalServer / QLocalSocketconst QString serverName = "MyCompany_MyProduct_UntitledApp_SingleInstance";// 先尝试连接已有的 server,如果能连上,说明已有实例在运行QLocalSocket socket;socket.connectToServer(serverName);if (socket.waitForConnected(100)) {// 给已运行实例发一个简单消息,用于激活窗口socket.write("activate");socket.flush();socket.waitForBytesWritten(100);socket.disconnectFromServer();// 这里仍然需要退出当前进程,但旧实例会弹出/激活自己的窗口return 0;}// 如果之前异常退出,可能遗留 serverName,先清理一次QLocalServer::removeServer(serverName);QLocalServer server;server.listen(serverName);MainWindow w;w.show();// 当有“第二个实例”连上来时,激活当前窗口QObject::connect(&server, &QLocalServer::newConnection, &w, [&]() {QLocalSocket *clientConnection = server.nextPendingConnection();if (clientConnection) {clientConnection->readAll(); // 简单读一下消息,不做处理clientConnection->disconnectFromServer();clientConnection->close();clientConnection->deleteLater();}w.showNormal();w.raise();w.activateWindow();a.setActiveWindow(&w);});return a.exec();
}
