原本项目中使用QSharedMemory的方法来判断当前是否已存在运行的实例,但在MacOS上,当程序异常崩溃后,QSharedMemory没有被正常销毁,导致应用程序无法再次被打开。
对此,Qt assistant中有相关说明:
摘抄 qt-solutions/qtsingleapplication at master · qtproject/qt-solutions (github.com) 实现了一个single application的类,记录下来:
main.cpp
- #include "mainwindow.h"
- #include "singleapplication.h"
-
- int main(int argc, char *argv[])
- {
- CSingleApplication a(argc, argv);
- if (a.isRunning()) {
- return 0;
- }
-
- MainWindow w;
- w.show();
- a.setActivationWindow(&w);
-
- return a.exec();
- }
singleapplication.cpp
- #include "singleapplication.h"
- #include
- #include
- #include
- #include
-
- CSingleApplication::CSingleApplication(int& argc, char** argv)
- : QApplication(argc, argv)
- {
- m_strServerName = QFileInfo(QCoreApplication::applicationFilePath()).fileName();
- initLocalConn();
- }
-
- CSingleApplication::~CSingleApplication()
- {
-
- }
-
- bool CSingleApplication::isRunning()
- {
- return m_isRunning;
- }
-
- void CSingleApplication::setActivationWindow(QWidget* w)
- {
- m_pActivateWin = w;
- }
-
- void CSingleApplication::initLocalConn()
- {
- m_isRunning = false;
-
- QLocalSocket socket;
- socket.connectToServer(m_strServerName);
- if (socket.waitForConnected(200)) {
- m_isRunning = true;
- return;
- }
-
- createLocalServer();
- }
-
- void CSingleApplication::createLocalServer()
- {
- m_pLocalServer = new QLocalServer(this);
- connect(m_pLocalServer, &QLocalServer::newConnection, this, &CSingleApplication::onNewConnection);
- if (!m_pLocalServer->listen(m_strServerName)) {
- if (QAbstractSocket::AddressInUseError == m_pLocalServer->serverError()) {
- QLocalServer::removeServer(m_strServerName);
- m_pLocalServer->listen(m_strServerName);
- }
- }
- }
-
- void CSingleApplication::activateWindow()
- {
- if (nullptr != m_pActivateWin) {
- m_pActivateWin->show();
- m_pActivateWin->raise();
- m_pActivateWin->activateWindow();
- }
- }
-
- void CSingleApplication::onNewConnection()
- {
- if (nullptr == m_pLocalServer) {
- return;
- }
-
- QLocalSocket* socket = m_pLocalServer->nextPendingConnection();
- if (nullptr != socket) {
- socket->waitForReadyRead(300);
- delete socket;
- activateWindow();
- }
- }
singleapplication.h
- #ifndef CSINGLEAPPLICATION_H
- #define CSINGLEAPPLICATION_H
-
- #include
-
- class QLocalServer;
-
- class CSingleApplication : public QApplication
- {
- public:
- CSingleApplication(int& argc, char** argv);
- virtual ~CSingleApplication() override;
-
- public:
- bool isRunning();
- void setActivationWindow(QWidget* w);
-
- private:
- bool m_isRunning = false;
- QWidget* m_pActivateWin = nullptr;
- QString m_strServerName;
- QLocalServer* m_pLocalServer = nullptr;
-
- void initLocalConn();
- void createLocalServer();
- void activateWindow();
-
- private slots:
- void onNewConnection();
- };
-
- #endif // CSINGLEAPPLICATION_H