【Qt专栏】实现单例程序,禁止程序多开的几种方式
目录
一,简要介绍
二,实现示例(Windows)
1.使用系统级别的互斥机制
2.通过共享内存(进程间通信-IPC)
3.使用命名互斥锁(不推荐)
4.使用文件锁
5.通过网络端口检测
一,简要介绍
前言
- 禁止程序多开,也称为“单实例应用程序”或“单例应用程序”,是指通过各种手段防止同一个应用程序同时运行多个实例。这种方法可以提升应用程序的稳定性、资源利用效率和用户体验。
目的
- 禁止程序多开的主要目的是确保应用程序在同一时刻只能运行一个实例,防止资源浪费、数据冲突、混淆等问题,以提高应用程序的质量和用户满意度。
好处
- 资源管理:多个实例同时运行可能导致资源的浪费,如内存、CPU 使用率等。通过限制只能运行一个实例,可以更有效地管理系统资源。
- 数据一致性:如果应用程序涉及到对共享数据或状态的修改,多个实例同时运行可能会导致数据不一致的问题。通过禁止多开,可以避免这种情况。
- 减少冲突:多个实例可能尝试访问同一资源,如文件、数据库等,导致冲突和错误。禁止多开可以减少这种情况的发生。
- 避免混淆:如果应用程序依赖于特定的硬件或外部设备,多个实例可能会导致设备混淆或竞争,从而影响功能正常运行。
- 提升用户体验:当用户只期望运行一个实例时,多开可能会让用户感到困惑。通过禁止多开,可以提升用户的体验和易用性。
实现方式
- 系统级别互斥机制:使用操作系统提供的互斥机制,如命名互斥体等。
- 共享内存或命名管道:使用共享内存或命名管道在不同实例间进行通信,防止多开。
- 命名互斥锁或文件锁:创建一个唯一名称的互斥锁或文件锁,如果已经存在,表示已有实例运行。
- 网络端口检测:尝试绑定到一个特定的网络端口,如果绑定成功,则表示没有其他实例在运行。
- 环境变量检测:检查环境变量,如已设置则表示已有实例运行。
总结
- 总之,禁止程序多开是一种优化应用程序的方法,可以确保应用程序在不同环境中稳定、高效地运行。选择适合的实现方式取决于应用程序的需求和技术栈。
二,实现示例(Windows)
1.使用系统级别的互斥机制
- 某些操作系统提供了系统级别的互斥机制,可以防止同一应用程序的多个实例运行。例如,Windows 提供了命名互斥体来实现这一点。
- 示例模板
- 示例代码
#include "mainwindow.h" #include <QApplication> #include <QMessageBox> #include <Windows.h>int main(int argc, char *argv[]) {QApplication a(argc, argv);// L"字符串":表示将ANSI字符串转换成unicode的字符串,使每个字符占两个字节HANDLE hMutex = CreateMutex(nullptr, TRUE, (LPCWSTR)qApp->applicationName().toStdWString().c_str());if (GetLastError() == ERROR_ALREADY_EXISTS) {QMessageBox::warning(nullptr, "Error", "An instance of the application is already running.");CloseHandle(hMutex);hMutex = NULL;return 1;}// 在此处写你的应用程序逻辑代码MainWindow w;w.show();a.exec();// 完成后关闭互斥锁CloseHandle(hMutex);hMutex = NULL;return 0; }
2.通过共享内存(进程间通信-IPC)
- 使用进程间通信技术,例如共享内存,来检测是否已经有一个实例在运行。
- 示例模板(使用 Qt 的 QSharedMemory 进行进程间通信)
- 示例代码
#include "mainwindow.h" #include <QApplication> #include <QMessageBox> #include <QSharedMemory>int main(int argc, char *argv[]) {QApplication a(argc, argv);QSharedMemory sharedMemory(qApp->applicationName()); // 设置绑定的共享内存段的key值if(sharedMemory.attach()){QMessageBox::warning(nullptr, "Error", "An instance of the application is already running.");return 1;}else{sharedMemory.create(1); // 创建1byte大小的共享内存段}// 在此处写你的应用程序逻辑代码MainWindow w;w.show();a.exec();// 完成后分离共享内存sharedMemory.detach();return 0; }
3.使用命名互斥锁(不推荐)
- 在应用程序启动时创建一个命名互斥锁,确保只有一个实例可以获取锁,其他实例将被阻止。
- 示例模板
- 示例代码
#include "mainwindow.h" #include <QApplication> #include <QMessageBox> #include <QSystemSemaphore>int main(int argc, char *argv[]) {QApplication a(argc, argv);// 声明一个命名互斥锁,用于防止多开QSystemSemaphore semaphore(qApp->applicationName(), 1, QSystemSemaphore::Open);if (!semaphore.acquire()) {QMessageBox::warning(nullptr, "Error", "An instance of the application is already running.");return 1;}// 在此处写你的应用程序逻辑代码MainWindow w;w.show();a.exec();// 释放互斥锁,允许其他实例运行semaphore.release();return 0; }
4.使用文件锁
- 在应用程序启动时创建一个特定的文件锁,如果锁已存在,则表示已经有一个实例在运行。
- 示例模板
- 示例代码
#include "mainwindow.h" #include <QApplication> #include <QMessageBox> #include <QFile>int main(int argc, char *argv[]) {QApplication a(argc, argv);QFile lockFile(qAppName() +".lock");if (lockFile.exists()) {QMessageBox::warning(nullptr, "Error", "An instance of the application is already running.");return 1;}lockFile.open(QIODevice::WriteOnly);lockFile.write("Running"); // 向锁文件写入一些数据lockFile.close();// 在此处写你的应用程序逻辑代码MainWindow w;w.show();a.exec();// 完成后删除锁定文件lockFile.remove();return 0; }
5.通过网络端口检测
- 在应用程序启动时尝试绑定到一个特定的网络端口,如果绑定成功,则表示没有其他实例正在运行。
- 示例模板
- 示例代码
#include "mainwindow.h" #include <QApplication> #include <QMessageBox> #include <QTcpServer>int main(int argc, char *argv[]) {QApplication a(argc, argv);QTcpServer tcpServer;if (!tcpServer.listen(QHostAddress::LocalHost, 12345)) {QMessageBox::warning(nullptr, "Error", "An instance of the application is already running.");return 1;}// 在此处写你的应用程序逻辑代码MainWindow w;w.show();a.exec();// 完成后关闭服务器tcpServer.close();return 0; }
相关文章:

【Qt专栏】实现单例程序,禁止程序多开的几种方式
目录 一,简要介绍 二,实现示例(Windows) 1.使用系统级别的互斥机制 2.通过共享内存(进程间通信-IPC) 3.使用命名互斥锁(不推荐) 4.使用文件锁 5.通过网络端口检测 一…...
力扣26. 删除有序数组中的重复项
给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。 考虑 nums 的唯一元素的数量为 k ,你需要做…...
【机器学习】鸢尾花分类-逻辑回归示例
这段代码是一个完整的示例,展示了如何使用逻辑回归对鸢尾花数据集进行训练、保存模型,并允许用户输入数据进行预测。以下是对这段代码的总结:功能: 这段代码演示了如何使用逻辑回归对鸢尾花数据集进行训练,并将训练好的…...

Flink CDC介绍
1.CDC概述 CDC(Change Data Capture)是一种用于捕获和处理数据源中的变化的技术。它允许实时地监视数据库或数据流中发生的数据变动,并将这些变动抽取出来,以便进行进一步的处理和分析。 传统上,数据源的变化通常通过…...

Java集合sort排序报错UnsupportedOperationException处理
文章目录 报错场景排查解决UnmodifiableList类介绍 报错场景 我们使用的是PostgreSQL数据库,存储业务数据,业务代码使用的是Spring JPA我们做的是智慧交通信控平台,有个功能是查询展示区域的交通态势,需要按照不同维度排序展示区…...

安防监控/磁盘阵列存储/视频汇聚平台EasyCVR调用rtsp地址返回的IP不正确是什么原因?
安防监控/云存储/磁盘阵列存储/视频汇聚平台EasyCVR可拓展性强、视频能力灵活、部署轻快,可支持的主流标准协议有GB28181、RTSP/Onvif、RTMP等,以及厂家私有协议与SDK接入,包括海康Ehome、海大宇等设备的SDK等,能对外分发RTSP、RT…...
Spring boot开启定时任务
Cron表达式生成器 基于接口的方式 使用Scheduled 注解很方便,但缺点是当我们调整了执行周期的时候,需要重启应用才能生效,这多少有些不方便。为了达到实时生效的效果,那么可以使用接口来完成定时任务,统一将定时器信…...
package.json相关知识记录
一、相关字段 npm官方字段介绍 🍧 bin > 简单理解:指定命令的名称及路径 🍉 相当于想path中添加路径,局部安装是在./node_modules/.bin/,全局安装是在全局的bin目录 🍉 bin指定的文件必须…...
VueRouter使用详解(5000字通关大全)
Vue Router是一个官方的路由管理器,它可以让我们在Vue应用中实现单页面应用(SPA)的效果,即通过改变URL而不刷新页面来显示不同的内容。Vue Router可以让我们定义多个路由,每个路由对应一个组件,当URL匹配到…...
vue axios实现下载文件及responseType:blob注意事项
需要使用axios和js-file-download组件 npm install js-file-download --save npm install axios --save import fileDownload from fileDownload; // 引入fileDownload import axios from axios; // 引入axios axios({method: get,url: xxxxxxx,responseType: blob }).then(r…...

StringBuilder类分享(1)
一、StringBuilder说明 StringBuilder是一个可变的字符序列。这个类提供了一个与StringBuffer兼容的API,但不保证同步,即StringBuilder不是线程安全的,而StringBuffer是线程安全的。显然,StringBuilder要运行的更快一点。 这个类…...

Qt 打开文件列表选择文件,实现拖拽方式打开文件
1. 实现打开文件列表选择文件 1.1. 创建 Qt 工程,并添加几个简单控件 这里笔者选用的是 QMainWindow,创建好工程后在 ui 界面设计中添加 QLineEdit、QPushBtton至少这两个控件,如下图摆放。 1.2. 头文件中添加相关操作 在 mainwindow.h 中…...

[C/C++]天天酷跑游戏超详细教程-上篇
个人主页:北海 🎐CSDN新晋作者 🎉欢迎 👍点赞✍评论⭐收藏✨收录专栏:C/C🤝希望作者的文章能对你有所帮助,有不足的地方请在评论区留言指正,大家一起学习交流!ǹ…...

5G NR:RACH流程 -- Msg1之选择正确的PRACH时频资源
PRACH的时域资源是如何确定的 PRACH的时域资源主要由参数“prach-ConfigurationIndex”决定。拿着这个参数的取值去协议38211查表6.3.3.2-2/3/4,需要注意根据实际情况在这三张表中进行选择: FR1 FDD/SULFR1 TDDFR2 TDD Random access preambles can onl…...

在vue3项目中编辑的时候,解决对话框里边的数据和列表中的数据联动了。深复制
//分析原因是从列表中拿到的数据直接复制去修改就涉及到堆里变的内容是一样的,直接复制其实只是把引用地址赋值给变量了,解决方法是 浅复制和深复制。<!-- 审批流程管理 --> <template><div style"float: left; width: 250px;backgr…...

循环结构(个人学习笔记黑马学习)
while循环语句 在屏幕中打印0~9这十个数字 #include <iostream> using namespace std;int main() {int i 0;while (i < 10) {cout << i << endl;i;}system("pause");return 0; } 练习案例: 猜数字 案例描述:系统随机生成一个1到100之间的数字&…...

ceph中PGLog处理流程
正文 struct pg_log_entry_t {ObjectModDesc mod_desc; //用于保存本地回滚的一些信息,用于EC模式下的回滚操作bufferlist snaps; //克隆操作,用于记录当前对象的snap列表hobject_t soid; …...

macOS使用命令行连接Oracle(SQL*Plus)
Author: histonevonzohomail.com Date: 2023/08/25 文章目录 SQL\*Plus安装下载环境配置 SQL\*Plus远程连接数据库参考文献 原文地址:https://histonevon.top/archives/oracle-mac-sqlplus数据库安装:Docker安装Oracle数据库 (histonevon.top) SQL*Plus…...

Mac下使用Homebrew安装MySQL5.7
Mac下使用Homebrew安装MySQL5.7 1. 安装Homebrew & Oh-My-Zsh2. 查询软件信息3. 执行安装命令4. 开机启动5. 服务状态查询6. 初始化配置7. 登录测试7.1 终端登录7.2 客户端登录 参考 1. 安装Homebrew & Oh-My-Zsh mac下如何安装homebrew MacOS安装Homebrew与Oh-My-Zsh…...

centos安装Nginx配置Nginx
1. 查看操作系统有没有安装Nginx which nginx 2. 使用epel的方式进行安装(方法二) 先安装epel sudo yum install yum-utils 安装完成后,查看安装的epel包即可 sudo yum install epel 3 开始安装nginx 上面的两个方法不管选择哪个&…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...
线程与协程
1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指:像函数调用/返回一样轻量地完成任务切换。 举例说明: 当你在程序中写一个函数调用: funcA() 然后 funcA 执行完后返回&…...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...
Robots.txt 文件
什么是robots.txt? robots.txt 是一个位于网站根目录下的文本文件(如:https://example.com/robots.txt),它用于指导网络爬虫(如搜索引擎的蜘蛛程序)如何抓取该网站的内容。这个文件遵循 Robots…...

GC1808高性能24位立体声音频ADC芯片解析
1. 芯片概述 GC1808是一款24位立体声音频模数转换器(ADC),支持8kHz~96kHz采样率,集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器,适用于高保真音频采集场景。 2. 核心特性 高精度:24位分辨率,…...