【Qt专栏】实现单例程序,禁止程序多开的几种方式

目录

一,简要介绍

二,实现示例(Windows)

1.使用系统级别的互斥机制

2.通过共享内存(进程间通信-IPC)

3.使用命名互斥锁(不推荐)

4.使用文件锁

5.通过网络端口检测


一,简要介绍

前言

  • 禁止程序多开,也称为“单实例应用程序”或“单例应用程序”,是指通过各种手段防止同一个应用程序同时运行多个实例。这种方法可以提升应用程序的稳定性、资源利用效率和用户体验。

目的

  • 禁止程序多开的主要目的是确保应用程序在同一时刻只能运行一个实例,防止资源浪费、数据冲突、混淆等问题,以提高应用程序的质量和用户满意度。

好处

  1. 资源管理:多个实例同时运行可能导致资源的浪费,如内存、CPU 使用率等。通过限制只能运行一个实例,可以更有效地管理系统资源。
  2. 数据一致性:如果应用程序涉及到对共享数据或状态的修改,多个实例同时运行可能会导致数据不一致的问题。通过禁止多开,可以避免这种情况。
  3. 减少冲突:多个实例可能尝试访问同一资源,如文件、数据库等,导致冲突和错误。禁止多开可以减少这种情况的发生。
  4. 避免混淆:如果应用程序依赖于特定的硬件或外部设备,多个实例可能会导致设备混淆或竞争,从而影响功能正常运行。
  5. 提升用户体验:当用户只期望运行一个实例时,多开可能会让用户感到困惑。通过禁止多开,可以提升用户的体验和易用性。

实现方式

  1. 系统级别互斥机制:使用操作系统提供的互斥机制,如命名互斥体等。
  2. 共享内存或命名管道:使用共享内存或命名管道在不同实例间进行通信,防止多开。
  3. 命名互斥锁或文件锁:创建一个唯一名称的互斥锁或文件锁,如果已经存在,表示已有实例运行。
  4. 网络端口检测:尝试绑定到一个特定的网络端口,如果绑定成功,则表示没有其他实例在运行。
  5. 环境变量检测:检查环境变量,如已设置则表示已有实例运行。

总结

  • 总之,禁止程序多开是一种优化应用程序的方法,可以确保应用程序在不同环境中稳定、高效地运行。选择适合的实现方式取决于应用程序的需求和技术栈。

二,实现示例(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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/105889.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux 下 Mysql 的使用(Ubuntu20.04)

文章目录 一、安装二、使用2.1 登录2.2 数据库操作2.2.1 创建数据库2.2.2 删除数据库2.2.3 创建数据表 参考文档 一、安装 Linux 下 Mysql 的安装非常简单&#xff0c;一个命令即可&#xff1a; sudo apt install mysql-server检查安装是否成功&#xff0c;输入&#xff1a; …

使用kubeadm方式快速部署一个K8S集群

目录 一、环境准备 二、环境初始化 三、在所有主机上安装相关软件 1、安装docker 2、配置k8s的yum源 3、安装kubelet、kubeadm、kubectl 四、部署Kubernetes Master 五、加入Kubernets Node 六、部署CNI网络插件 七、测试k8s集群 一、环境准备 我的是CentOS7系统&am…

iOS App签名与重签名:从开发者证书到重新安装运行

前文回顾&#xff1a; iOS脱壳技术&#xff08;二&#xff09;&#xff1a;深入探讨dumpdecrypted工具的高级使用方法 iOS逆向&#xff1a;越狱及相关概念的介绍 在本文中&#xff0c;我们将详细介绍iOS应用的签名过程&#xff0c;包括开发者证书的种类、证书与App ID、Provisi…

利用 Apifox 的 Mock 功能模拟常见业务数据的最佳方法

Apifox 拥有强大的 Mock 功能&#xff0c;兼容 Mock.js 语法的同时还提供 Nunjucks 和自定义脚本支持&#xff0c;能够满足不同场景需求。 今天给大家分享一些常见业务场景的 Mock 使用技巧&#xff0c;当然&#xff0c;实现的方法不唯一。在开始之前&#xff0c;你需要将 Api…

【C++】list

list 1. 简单了解list2. list的常见接口3. 简单实现list4. vector和list比较 1. 简单了解list list的底层是带头双向循环列表。因此list支持任意位置的插入和删除&#xff0c;且效率较高。但其缺陷也很明显&#xff0c;由于各节点在物理空间是不连续的&#xff0c;所以不支持对…

Python项目开发案例————学生信息管理系统(附源码)

一、学生信息管理系统 本文使用Python语言开发了一个学生信息管理系统&#xff0c;该系统可以帮助教师快速录入学生的信息&#xff0c;并且对学生的信息进行基本的增、删、改、查操作&#xff1b;还可以实时地将学生的信息保存到磁盘文件中。 1.1 需求分析 为了顺应互联网时代…

软件测试及数据分析处理实训室建设方案

一 、系统概述 软件测试及数据分析处理是软件开发过程中的一项重要测试活动&#xff0c;旨在验证不同软件模块或组件之间的集成与交互是否正常。综合测试确保各个模块按照设计要求正确地协同工作&#xff0c;以实现整个软件系统的功能和性能。以下是软件测试及数据分析处理的一…

SpringMVC程序开发

前言&#xff1a; &#x1f4d5;作者简介&#xff1a;热爱编程的小七&#xff0c;致力于C、Java、Python等多编程语言&#xff0c;热爱编程和长板的运动少年&#xff01; &#x1f4d8;相关专栏Java基础语法&#xff0c;JavaEE初阶&#xff0c;数据库&#xff0c;数据结构和算法…

【位运算】算法实战

文章目录 一、算法原理常见的位运算总结 二、算法实战1. leetcode面试题01.01. 判断字符是否唯一2. leetcode268 丢失的数字3. leetcode371 两整数之和4. leetcode004 只出现一次的数字II5. leetcode面试题17.19. 消失的两个数字 三、总结 一、算法原理 计算机中的数据都以二进…

香港服务器怎么打开SSH

​  SSH是一种远程登录协议&#xff0c;可以通过加密方式在网络上安全地传输数据。它允许用户在远程服务器上执行命令&#xff0c;管理文件和目录&#xff0c;并进行其他系统管理任务。 如何打开SSH服务? 1.确认已安装OpenSSH服务器&#xff1a; 你可以通过命令sudoapt-geti…

开发一款AR导览导航小程序多少钱?ar地图微信小程序 ar导航 源码

随着科技的不断发展&#xff0c;增强现实&#xff08;AR&#xff09;技术在不同领域展现出了巨大的潜力。AR导览小程序作为其中的一种应用形式&#xff0c;为用户提供了全新的观赏和学习体验。然而&#xff0c;开发一款高质量的AR导览小程序需要投入大量的时间、人力和技术资源…

Sql Server导出数据库到另一个数据库

1.打开sql server数据库&#xff0c;连接到服务器后&#xff0c;找到需要导出的数据库&#xff0c;右击后选择 任务->导出数据。 2.点击 下一步。 3.身份验证可以使用SQL Server身份验证&#xff0c;就是当时建立连接时的用户名和密码&#xff0c;数据库名称使用默认的&…

Kafka生产者原理 kafka生产者发送流程 kafka消息发送到集群步骤 kafka如何发送消息 kafka详解

kafka尚硅谷视频&#xff1a; 10_尚硅谷_Kafka_生产者_原理_哔哩哔哩_bilibili ​ 1. producer初始化&#xff1a;加载默认配置&#xff0c;以及配置的参数&#xff0c;开启网络线程 2. 拦截器拦截 3. 序列化器进行消息key, value序列化 4. 进行分区 5. kafka broker集群 获取…

数据库为什么使用B+树而不是B树做索引

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;CSDN领军人物&#xff0c;全栈领域优质创作者✌&#xff0c;CSDN博客专家&#xff0c;阿里云社区专家博主&#xff0c;2023年6月CSDN上海赛道top4。 &#x1f3c6;数年电商行业从业经验&#xff0c;历任核心研发工程师…

华为质量管理:从产品质量到用户体验,Kano模型成为新方向

目录 前言 华为质量管理的四个阶段 基于 IPD 如何做质量管理呢&#xff1f; CSDN相关课程 作者简介 前言 今天继续来谈谈华为流程体系中的质量管理过程。 通常来说质量具体是指产品的质量&#xff0c;也就是产品的使用价值及其属性。 产品再细分的话可以分为三个层次&a…

Python 数据分析——matplotlib 快速绘图

matplotlib采用面向对象的技术来实现&#xff0c;因此组成图表的各个元素都是对象&#xff0c;在编写较大的应用程序时通过面向对象的方式使用matplotlib将更加有效。但是使用这种面向对象的调用接口进行绘图比较烦琐&#xff0c;因此matplotlib还提供了快速绘图的pyplot模块。…

《vue3实战》在created生命周期中运用slice()方法结合element plus组件实现电影评价系统的分页

目录 前言 电影评价系统的分页是什么&#xff1f;它具体的作用体现在哪些方面&#xff1f; 一、slice的含义、语法和作用以及created的作用 slice是什么&#xff1f;slice有什么语法&#xff1f;slice的作用体现在哪些方面&#xff1f; created生命周期的作用&#xff1a;…

K8S cluster with multi-masters on Azure VM

拓扑参考&#xff1a; 在 Azure VM 实例上部署 KubeSphere 基础模板 需要修改 IP 地址和 VM Image的可以在模板中修改。 {"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#","contentVersion": &q…

云计算存储类型

一、共享存储模式 NAS: ①一种专门用于存储和共享文件的设备&#xff0c;它通过网络连接到计算机或其他设备&#xff0c; 提供了一个中心化的存储解决方案 ②存储网络使用IP网络 &#xff0c;数据存储共享基于文件 ③本质上为:NFS和CIFS文件共享服务器 ④提供的不是一个磁盘块…

python使用 flask+vue 制作前后端分离图书信息管理系统

目录标题 前言制作前后端分离图书信息管理系统的思路&#xff1a;素材代码效果展示 后端部分接口部分前端部分尾语 前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! 哈喽兄弟们&#xff0c;今天咱们来用Python实现一个前后端分离的图书信息管理系统。 制作前后端分离图书信…