Qt实现程序单实例运行(只能运行1个进程)及QSharedMemory用法

1. 问题提出

        在开发时,经常遇到这样的需求或场景:程序只能被启动一次,不能启动多次,启动多次会导致混乱,如:可执行程序用到文件指针、串口句柄等。试想如果存在多个同一个文件的句柄或同一个串口的句柄,就可能在同一时刻对同一文件或串口进行写操作,这样会导致文件内容杂乱、损坏;现实中,当一个串口被一个程序占用时,另外一个程序尝试打开这个串口会报错,因此需要控制程序运行时只能开启一个实例,如何用Qt实现程序单实例运行?

2. 实现方法

         直接上代码,看代码注释就能理解

#include <QSharedMemory>
#include <QDebug>
bool programIsRunning(QSharedMemory**ppSharedMemory)
{/* 为共享内存定义一个字符串类型的key,该key用于标识共享内存对象。* key可以是任意字符串,但必须保证程序运行的机器上不能同时存在同样* 字符串表示的共享内存对象,否则就会造成共享内存访问混乱*/const auto key = QString(QLatin1String("huaHaiFCSoftWare"));bool isRunning = false;auto pSharedMemory = new QSharedMemory(key); // 创建共享内存对象/* 将指向共享内存对象的指针的地址保存到一个二级指针上,* 便于程序退出时,删除该共享内存对象*/ppSharedMemory = &pSharedMemory;// 创建一段大小为1024的共享内存段auto b = pSharedMemory->create(1024);/* 创建共享内存时也许出错了,获取错误码*/auto errNo = pSharedMemory->error();/* 后续代码要读写刚才创建的共享内存中的内容,* 在读写共享内存之前要锁定该段共享内存,防止共享内存的内容被另外的* 进程或本程序的另外一个实例更改,有点类似多线程下访问数据需要加锁*/pSharedMemory->lock();/* 如果上面create创建共享内存成功,那么就向共享内存* 写入一点东西,写入的东西可随意,这里写入的是共享内存对象的标识符*/if(b){auto pSharedMemoryData = static_cast<char*>(pSharedMemory->data()); // 获取共享内存的数据指针strncpy_s(pSharedMemoryData, 1024, key.toStdString().c_str(), strlen(key.toStdString().c_str()) + 1);}/** 如果上面create创建共享内存失败,且失败的原因是该段共享内存存在了,证明* 存在本程序的一个实例已经在运行,该段共享内存就是这个已经在运行的实例创建的*/else if(!b && (QSharedMemory::AlreadyExists == errNo)){/* 以读写模式将事先已经在运行的本程序的实例进程附到这段共享内存上,* 如果不调用attach,则data()函数将返回nullptr*/pSharedMemory->attach();auto pSharedMemoryData = static_cast<char*>(pSharedMemory->data());/*将共享内存的内容读出并检测是否和以前写入*共享内存的内容一样,如果一样,证明本程序的*一个实例已经在运行,则就将正在运行标志isRunning设置为true*/if((nullptr != pSharedMemoryData) && !strcmp(pSharedMemoryData, key.toStdString().c_str())){qDebug() << QStringLiteral("程序已经在运行,\n同一程序不能开启多个!");isRunning = true;}}pSharedMemory->unlock(); // 访问完共享内存后,要解锁,否则其它进程或本程序的其它实例访问不了这段共享内存/* 注意:不能在本函数delete共享内存对象,否则create创建的共享内存的内容会释放,这样会造成本程序的多个实例启动时,会检测不到有本程序的实例已经在运行*///  delete pSharedMemory;return isRunning;
}int main(int argc, char *argv[])
{QApplication a(argc, argv);QSharedMemory**ppSharedMemory = nullptr;// 如果发现本程序的一个实例已经在运行,则本次启动的实例进程直接退出if(programIsRunning(ppSharedMemory)){delete ppSharedMemory;return 1;}// 程序的其它代码略auto nRet = a.exec();// 当程序完全退出时才删除创建的共享内存对象delete ppSharedMemory;return nRet;
}

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

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

相关文章

开源网关Apache APISIX启用JWT身份验证

说明&#xff1a; 本文APISIX的配置参考我之前写的《Ubuntu部署Apache APISIX》 创建最小API 首先&#xff0c;确保你已经安装了.NET 6 SDK。创建文件夹“MinimalApiDemo”&#xff0c;VS Code打开文件夹&#xff0c;打开终端 dotnet new web -o MinimalApiDemo cd Minimal…

python字典包连接mysql

连接mysql, 使用清华大学或其他国内 PyPI 镜像源 如果你在中国&#xff0c;由于网络问题&#xff0c;连接到 Oracle 的官方仓库可能会很慢或失败。在这种情况下&#xff0c;你可以使用国内的 PyPI 镜像源。例如&#xff0c;使用清华大学的镜像源&#xff1a; bash复制代码 pi…

鸿蒙开发接口数据管理:【@ohos.data.distributedData (分布式数据管理)】

分布式数据管理 分布式数据管理为应用程序提供不同设备间数据库的分布式协同能力。通过调用分布式数据各个接口&#xff0c;应用程序可将数据保存到分布式数据库中&#xff0c;并可对分布式数据库中的数据进行增加、删除、修改、查询、同步等操作。 该模块提供以下分布式数据…

Spring的bean的生命周期

想象一下&#xff0c;Spring中的Bean就像是你家后院种植的一株植物&#xff0c;从播种到开花结果&#xff0c;再到最后枯萎&#xff0c;整个过程就像是Bean的生命周期。现在&#xff0c;让我们以这个比喻来了解一下Spring Bean的生命周期吧&#xff1a; 1. 播种&#xff08;…

49.线程池的关闭方法

shutdown方法 1.线程池状态变为shutdown 2.不会接收新任务 3.已提交的任务会执行完 4.此方法不会阻塞调用线程执行 ExecutorService executorService = Executors.newFixedThreadPool(2);executorService.submit(() -> {log.debug("task1 running");try {TimeUnit…

ArrayList——简单洗牌算法

特殊语法介绍&#xff1a; List<List<E>> 该语法情况比较特殊&#xff0c;相当于一个“二维数组”存着一个个线性表的结构&#xff0c;如图&#xff1a; 该语法的灵活性强&#xff0c;可适用于多种类型和多种情况。接下来就使用该语法来实现一个简单的洗牌操作。…

Laravel常用数据库操作指令(模型/DB)

1、使用模型操作数据库&#xff0c;需要先引入相应的模型 如:use App\Models\Test; 2、使用DB操作数据库需要先引入DB库 如:use Illuminate\Support\Facades\DB; 一、数据库查询操作 get方法&#xff1a; 写法一:Test::select(id,name)->where(id,,1)->get();//sel…

vite+ts设置别名

准备工作 安装 types/node 避免代码爆红 npm install types/node一、根目录下 vite.config.ts 文件中配置 import { resolve } from path;resolve: {// 设置文件./src路径为 alias: [{find: ,replacement: resolve(__dirname, ./src)}] }二、根目录下 tsconfig.json 文件中配…

【漏洞复现】用友NC downCourseWare 任意文件读取漏洞

0x01 产品简介 用友NC是一款企业级ERP软件。作为一种信息化管理工具&#xff0c;用友NC提供了一系列业务管理模块&#xff0c;包括财务会计、采购管理、销售管理、物料管理、生产计划和人力资源管理等&#xff0c;帮助企业实现数字化转型和高效管理。 0x02 漏洞概述 用友NC …

618网购节,电商能挡住恶意网络爬虫的攻击吗?

目录 爬虫盗取电商数据的步骤 电商平台如何发现网络爬虫&#xff1f; 如何拦截违法网络爬虫 2023年&#xff0c;杭州中院审结了两起涉及“搬店软件”的不正当竞争案件。本案的原告是国内某大型知名电子商务平台的运营主体&#xff0c;而被告则是开发了一款名为“某搬家快速商品…

汽车分销商文件流转优化:实现稳定高效的文件分发处理

在汽车圈里&#xff0c;分销商可是个不可或缺的角色。他们既要跟汽车厂家紧紧绑在一起&#xff0c;还得跟下游的销售渠道或者直接跟消费者打成一片&#xff0c;文件来回传递那是家常便饭。 这文件发放的速度快不快&#xff0c;安不安全&#xff0c;直接影响到分销商做事的效率…

安徽京准NTP时钟系统:GPS北斗卫星授时下的生活重塑

安徽京准NTP时钟系统&#xff1a;GPS北斗卫星授时下的生活重塑 安徽京准NTP时钟系统&#xff1a;GPS北斗卫星授时下的生活重塑 时间的流逝自古以来时钟都是人类生活与活动的基础。然而&#xff0c;随着科技的进步&#xff0c;我们对时间管理和测量的方法已经发生了翻天覆地的变…

有哪些可以替代postman的接口测试软件?

替代Postman的接口测试软件有很多选择&#xff0c;其中一些流行的工具包括Insomnia、SoapUI、JMeter、Paw等。在本篇文章中&#xff0c;我将从0到1&#xff0c;详细介绍这些接口测试软件的使用方法和规范&#xff0c;帮助你选择适合的工具进行接口测试。 1. Insomnia Insomni…

手机怎么压缩视频?归纳了三种快速压缩方案

手机怎么压缩视频&#xff1f;在数字时代&#xff0c;手机已经成为我们记录生活的重要工具&#xff0c;而视频作为其中的一种主要形式&#xff0c;更是占据了极大的存储空间。然而&#xff0c;随着手机拍摄的视频越来越多&#xff0c;如何高效压缩视频以节省存储空间&#xff0…

力扣 75.颜色分类

给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums&#xff0c;原地对它们进行排序&#xff0c;使得相同颜色的元素相邻&#xff0c;并按照红色、白色、蓝色顺序排列。我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。 使用sort函数可以不考虑算法&#xff1a; clas…

⌈ 传知代码 ⌋ AI驱动食物图像识别

&#x1f49b;前情提要&#x1f49b; 本文是传知代码平台中的相关前沿知识与技术的分享~ 接下来我们即将进入一个全新的空间&#xff0c;对技术有一个全新的视角~ 本文所涉及所有资源均在传知代码平台可获取 以下的内容一定会让你对AI 赋能时代有一个颠覆性的认识哦&#x…

Selenium时间等待_显示等待

特点&#xff1a; 针对具体元素进行时间等待 可以自定义等待时长和间隔时间 按照设定的时间&#xff0c;不断定位元素&#xff0c;定位到了直接执行下一步操作 如在设定时间内没定位到元素&#xff0c;则报错&#xff08;TimeOutException&#xff09; 显示等待概念&#x…

mysql的binlog占用大量磁盘空间的解决方法

查看当前日志保存天数&#xff1a; mysql> show variables like %expire_logs_days%; ------------------------- | Variable_name | Value | ------------------------- | expire_logs_days | 0 | ------------------------- 1 row in set (0.08 sec) 默认是0&…

基于Python的实验室管理系统的设计与实现(论文+源码)_kaic

摘 要 随着实验室设备越来越多&#xff0c;实验室及其设备管理工作变得越来越繁重&#xff0c;还存在些管理模式仍旧处于手工管理模式和一些抢占实验室的不文明现象&#xff0c;传统的手工模式已经满足不了日益增长的管理需求&#xff0c;而本系统摒弃传统模式&#xff0c;开启…

高校运维赛 2024 pyssrf

没有环境,简单过一遍思路吧 考点: pickle反序列化urllib库注入redis缓存 from flask import Flask,request from redis import Redis import hashlib import pickle import base64 import urllib app Flask(__name__) redis Redis(host127.0.0.1, port6379)def get_result(u…