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

news2024/9/28 3:21:08

目录

一,简要介绍

二,实现示例(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.coloradmin.cn/o/929470.html

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

相关文章

visual studio 2022.NET Core 3.1 未显示在目标框架下拉列表中

问题描述 在Visual Studio 2022我已经安装了 .NET core 3.1 并验证可以运行 .NET core 3.1 应用程序&#xff0c;但当创建一个新项目时&#xff0c;目标框架的下拉列表只允许 .NET 6.0和7.0。而我在之前用的 Visual Studio 2019&#xff0c;可以正确地添加 .NET 核心项目。 …

Dev-C++ 下载和安装

TOC 1. 下载 Dev-C 访问 sourceforge 网站&#xff0c;然后单击 Download&#xff0c; 2. 安装 Dev-C 双击下载的安装文件进行安装。 3. 在线环境 https://cpp.sh/ 完结&#xff01;

IDEA中GIT相关操作

文章目录 IDEA中GIT相关操作IDEA TAG 提交查看某个tag版本代码、根据某个tag创建分支将分支代码合并到主分支 IDEA中GIT相关操作 IDEA TAG 提交 1.创建tag 右键项目&#xff0c;然后按照 Git -> Repository -> Tag… 创建tag。 或 顶部菜单栏 按照 VCS -> Git->…

27- v-model 原理 组件应用

v-model 原理 原理: V-model本质上是一个语法糖。例如应用在输入框上&#xff0c;就是 value属性 和 input事件 的合写 作用: 提供数据的双向绑定 (1) 数据变,视图跟着变 : value (2) 试图变,数据跟着变: input 注意: $event 用于在模板中, 获取事件的形参 <template>…

YOLOv5算法改进(5)— 添加ECA注意力机制

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。ECA注意力机制是一种用于图像处理中的注意力机制&#xff0c;是在通道注意力机制的基础上做了进一步的改进。通道注意力机制主要是通过提取权重&#xff0c;作用在原特征图的通道维度上&#xff0c;而ECA注意力机制则使用了…

人力资源小程序的设计方案与实现

随着互联网的发展&#xff0c;人才招聘已经成为许多企业的一项重要任务。为了提高招聘效率和便利求职者&#xff0c;许多企业开始采用小程序作为招聘平台。本文将为大家介绍一个搭建本地人才招聘网小程序的实用指南。 首先&#xff0c;我们需要登录【乔拓云】制作平台&#xff…

信创国产系统麒麟arm架构中nginx安装过程

前言 在事业单位或国企&#xff0c;信创项目在步步推进&#xff0c;下面将在国产系统通信arm架构中nginx的安装过程记录分享出来&#xff0c;希望帮助到有需要的小伙伴。 1、nginx下载 1.1、在线下载 进入指定目录&#xff0c;如/usr/local&#xff0c;执行如下命令&#x…

DataFrame.plot函数详解(二)

DataFrame.plot函数详解&#xff08;二&#xff09; 1. Line 1.1主要参数 import matplotlib.pyplot as plt import pandas as pd import numpy as npdf pd.Series(abs(np.random.randn(10)), index pd.date_range(2020-01-01, periods 10)) df.plot.line(style :,marker…

【51单片机】EEPROM-IIC实验(按键控制数码管)

目录 &#x1f381;I2C总线 ​编辑 &#x1f381;代码 &#x1f3f3;️‍&#x1f308;main.c &#x1f3f3;️‍&#x1f308;i2.c &#x1f386;代码分析 &#x1f381;I2C总线 I2C总线是Philips公司在八十年代初推出的一种串行、半双工的总线&#xff0c;主要用于近距…

xsschallenge通关(1-10)

文章目录 level1level 2level 3level 4level 5level 6level 7level 8level9level 10 level1 这一关很简单&#xff0c;标准的xss注入&#xff0c;打开hackbar&#xff0c;输入 <script>alert(/xss/)</script>点击EXECUTE&#xff0c;通关&#xff01; level 2 这…

HTML <template> 标签

实例 使用 <template> 保留页面加载时隐藏的内容。使用 JavaScript 来显示: <button οnclick="showContent()">显示被隐藏的内容</button><template><h2>Flower</h2><img src="img_white_flower.jpg" width=&q…

微服务框架 go-zero 快速实战

对于咱们快速了解和将 go-zero 使用起来&#xff0c;我们需要具备如下能力&#xff1a; 基本的环境安装和看文档的能力 Golang 的基本知识 Protobuf 的基本知识 web&#xff0c;rpc 的基本知识 基本的 mysql 知识 其实这些能力&#xff0c;很基础&#xff0c;不需要多么深入&a…

MAE 论文精读 | 在CV领域自监督的Bert思想

1. 背景 之前我们了解了VIT和transformer MAE 是基于VIT的&#xff0c;不过像BERT探索了自监督学习在NLP领域的transformer架构的应用&#xff0c;MAE探索了自监督学习在CV的transformer的应用 论文标题中的Auto就是说标号来自于图片本身&#xff0c;暗示了这种无监督的学习 …

15 html简介

文章目录 html 概述和基本结构html概述html的基本结构HTML 文档类型xhtml 1.0 &#xff08;html4&#xff09;html5 两种文档的区别html 注释 html标签介绍html 标题标签html 段落标签、换行标签与字符实体html 段落标签html 换行标签html 字符实体 html 块标签、含样式的标签h…

28- .sync修饰符:父子双向绑定

作用: 可以实现 子组件 与 父组件数据 的 双向绑定&#xff0c;简化代码 特点: prop属性名&#xff0c;可以自定义&#xff0c;非固定为 value 场景: 封装弹框类的基础组件&#xff0c;visible属性 true显示 false隐藏 本质: 就是 :属性名 和 update:属性名 合写

打开软件提示msvcp140.dll丢失的解决方法,msvcp140主要丢失原因

今天&#xff0c;我将为大家介绍一种非常常见的问题——msvcp140.dll丢失。这个问题可能会导致许多应用程序无法正常运行&#xff0c;甚至崩溃。但是&#xff0c;请不要担心&#xff0c;我会为大家提供5种解决方法&#xff0c;帮助大家轻松解决问题。 首先&#xff0c;我们来看…

Android 13 - Media框架(8)- MediaExtractor

上一篇我们了解了 GenericSource 需要依赖 IMediaExtractor 完成 demux 工作&#xff0c;这一篇我们就来学习 android media 框架中的第二个服务 media.extractor&#xff0c;看看 IMediaExtractor 是如何创建与工作的。 1、MediaExtractorService media.extractor 和 media.p…

【ArcGIS微课1000例】0071:普通最小二乘法 (OLS)回归分析案例

严重声明:本文来自专栏《ArcGIS微课1000例:从点滴到精通》,为CSDN博客专家刘一哥GIS原创,原文及专栏地址为:(https://blog.csdn.net/lucky51222/category_11121281.html),谢绝转载或爬取!!! 文章目录 一、空间自回归模型二、ArcGIS普通最小二乘法回归(OLS)一、空间自…

企业ADManager Plus软件的使用案例

引言&#xff1a; 在当今数字化时代&#xff0c;企业的活动主要依赖于信息技术和计算机系统。作为关键的IT基础架构组件之一&#xff0c;Active Directory&#xff08;AD&#xff09;在维护和管理用户、计算机和资源方面发挥着关键作用。AD的高效管理对于确保企业的平稳运行至…

HDFS 集群读写压测

文章目录 虚拟机设置HDFS 写数据测试HDFS 读数据测试删除压测产生的数据 虚拟机设置 如果你是在虚拟机中使用集群&#xff0c;那你你需要先对每台服务器进行网络设置&#xff0c;模拟真实网络传输速率。 如下所示&#xff1a; 将其设置为百兆网&#xff0c;每台服务器都要进行…