Qt下让程序只运行一个实例,避免重复打开

参考
【实现QT单例程序 QSystemSemaphore QSharedMemory】
做了一点点更改,主要是在openEuler上用时遇到的一点问题。

QSharedMemory *unimem = nullptr;
void checkExist()
{
    QString memName = "SingleApp"; // 注意这名字要每个工程不一样,否则不同的exe可能会冲突
    
    // 信号量的意义,把操作共享内存的代码锁住。因为有可能同时点击2次APP, 防止并发
    QSystemSemaphore sema(memName + "Key", 1, QSystemSemaphore::Open);
    qDebug() << "sema.acquire:" << sema.acquire();

#ifdef Q_OS_LINUX
    /* Windows平台上不存在应用程序崩溃后,共享内存段还存在的情况
     * LINUX应用程序崩溃后,共享内存段不会自动销毁,则该程序再次运行会出问题
     * 所以程序启动时先去检查是否有程序崩溃后还存留的共享内存段,如果有,先销毁,再创建
     */
    QSharedMemory mem(memName);
    // 尝试将进程附加到共享内存段
    if (mem.attach()) {
        // 将共享内存与主进程分离, 如果此进程是附加到共享存储器段的最后一个进程,则系统释放共享存储器段,即销毁内容
        mem.detach();
    }
    else
    {
        // 假如权限不足的话,也是无法attach的
        qDebug() << "linux:" << mem.errorString();
    }
#endif

    /*
     * 每个App打开的时候,获取一次共享内存。
     * 如果获取失败,说明是第一个启动的APP,直接创建共享内存就好了。假如创建失败,说明不是第一个,直接退出就好了。
     * 如果获取成功,说明不是第一个,也是直接退出就好了。
     * 保证App在系统里只能打开一个。
     */
    unimem = new QSharedMemory(memName);
    bool isRunning = false;
    if (unimem->attach()) {
        isRunning = true;
    } else {
        bool ret = unimem->create(1);
        if(ret == false) // 主要是改了这里
        {
            qDebug() << "create uniMem:" << ret << unimem->error() << unimem->errorString();
            if(unimem->error() != QSharedMemory::NoError)
            {
                isRunning = true;
            }
        }
        else
        {
            isRunning = false;
        }
    }

    sema.release();

    if (isRunning) {
        //        qWarning() << QStringLiteral("已经有一个实例在运行,即将退出");
        std::cout << QString("已经有一个实例在运行,即将退出").toLocal8Bit().data() << std::endl;
        exit(0);
    }
}

在主函数实例化Application后,调用即可。


int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    checkExist();
    ...
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值