原本项目中使用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 <QFileInfo>
#include <QLocalSocket>
#include <QLocalServer>
#include <QWidget>
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 <QApplication>
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