越来越多的 windows 桌面程序要求防止重复启动,或者说只允许同时启动一个。实现方式有很多,我们接下来梳理一下常用的做法:

一、创建互斥量 

原理:使用 windows 系统函数 CreateMutex
,一般根据唯一的应用程序的名称来找出当前系统中是否已经存在了指定进程的实例,如果没有,则会创建一个。

注意: 程序退出时,一定要调用CloseHandle(m_hMutex),不然后果很严重,可能导致以后的程序无法打开。
#include "stdafx.h" #include "windows.h" int main(int argc, char* argv[]) {
HANDLE m_hMutex = CreateMutex(NULL, TRUE, "my_app_name"); DWORD dwRet =
GetLastError(); if (m_hMutex) { if (ERROR_ALREADY_EXISTS == dwRet) {
printf("程序已经在运行中了,程序退出!\n"); CloseHandle(m_hMutex); return 0; } } else {
printf("创建互斥量错误,程序退出!\n"); CloseHandle(m_hMutex); return 0; } while(1) {
printf("my_app_name\n"); } CloseHandle(m_hMutex); return 0; }
二、使用QLockFile 创建锁定文件,通过能否锁定来判断是否已经有程序启动。

原理:使用Qt 提供的对象
QLockFile。它提供一个文件的进程间的锁定。锁文件可用于防止多个进程同时访问统一资源。只有当访问共享资源的所有进程使用相同的文件路径的QLockFile时,才能保证序列化。 使用使用
tryLock() 函数来尝试锁定文件,锁定成功了,就说明没有已经启动的程序。锁定失败则表示已经有程序在启动了。

注意:

1. 创建一个临时文件(一般创建在临时目录内)。

2. 一般使用tryLock 要设置超时时间,时间一般不易过久。
#include <QApplication> #include <QLockFile> #include <QDir> #include <QDebug>
int main(int argc, char *argv[]) { QApplication a(argc, argv); QString tempPath
= QApplication::applicationDirPath() + "/temp/"; QString filePath = tempPath +
"/" + "my_app_name" + ".app.lock"; QLockFile *lockFile = new
QLockFile(filePath); if (lockFile->tryLock(2000)) { qDebug() << "运行程序成功!"; }
else { qDebug() << "程序已经在运行中了,程序退出"; return 0 ; } if (lockFile) { delete
lockFile; } return a.exec(); }
二、使用 系统信号量 QSystemSemaphore 与 共享内存 QSharedMemory

原理:

1. 信号量 QSystemSemaphore:
为系统级别信号量,可以再多个进程间使用。多个进程可以通过名字来操作一个信号量。创建时候需要指定一个mode,可以选择Open 和 Create
。其中,Open在请求的信号量已存在时,就使用它,并且不会重置信号的资源数,如果请求的信号量不存在,就
创建它并为它设置初始的资源值。而对于Create来说,不管请求的信号量是否已存在,它都会取得信号量的拥有权,并设置初始值。所以,我们应该在第一次创建信号量时,为其传入Create参数。但在Windows平台上,Create和Open的行为相同,因为,Windows平台上不存在应用程序崩溃后,信号量还存在的情况。

信号量简单的来说就是谁先请求,谁就可以继续操作,只有释放了之后,别的程序才可以继续。所以
信号量也可以理解为一种简单的互斥锁,保护某种资源不会同时被多个程序操作。

使用系统信号量就是为了保护共享内存不会被多个进程同时操作。

注意:

1. 信号量的启动 acquire() 和释放 release() 必须是成对出现。要保护资源的操作要在 acquire() 和 release()
中间操作。
#include <QApplication> #include <QSharedMemory> #include <QSystemSemaphore>
#include <QDebug> int main(int argc, char *argv[]) { QApplication a(argc,
argv); // 创建信号量 QSystemSemaphore semaphore("myAppSemaphore", 1); //
启用信号量,禁止其他实例通过共享内存一起工作 semaphore.acquire(); // 创建一个共享内存 myAppName 可作为唯一程序的标识
QSharedMemory sharedMemory1("myAppName"); bool isRunning = false; //
试图将共享内存的副本附加到现有的段中。 if (sharedMemory1.attach()) { // 如果成功,则确定已经存在运行实例 isRunning
= true; } else { // 否则申请一字节内存 sharedMemory1.create(1); // 确定不存在运行实例 isRunning =
false; } semaphore.release(); if (isRunning) { qDebug() << "程序已经在运行中了,程序退出";
return 0; } return a.exec(); }

技术
下载桌面版
GitHub
Gitee
SourceForge
百度网盘(提取码:draw)
云服务器优惠
华为云优惠券
腾讯云优惠券
阿里云优惠券
Vultr优惠券
站点信息
问题反馈
邮箱:[email protected]
吐槽一下
QQ群:766591547
关注微信