Qt实现检测软件是否多开

news2024/11/23 18:32:01

Qt实现检测软件是否多开

在桌面软件开发中,软件通常要设置只允许存在一个进程,像一些熟知的音乐软件,QQ音乐这种。而这些软件在限制只有一个进程的同时,通常还会有双击桌面图标唤醒已运行的后台进程的功能。关于双击桌面唤醒已运行进程的方法,请看这篇文章:
本文中所介绍的各种方法,都基本遵循一个基本逻辑,即:“还未完成”
监测同一个资源,根据资源的占用情况,来决定是否能够启动。

平台特殊

操作系统提供了一些API供我们使用,所以接下来介绍一些使用特定系统API的方法。

windows

CreateMutex

image.png
具体API内容请看:MS Learn CreateMutexW
简单来讲,就是创建一个指定命名的互斥对象。当这个互斥对象已存在时,函数将会返回一个错误。

如果 lpName 与现有事件、信号量、可等待计时器、作业或文件映射对象的名称匹配,则函数将失败, GetLastError 函数返回 ERROR_INVALID_HANDLE

思路

通过这个错误,我们就能判断互斥对象创建成功还是失败,进一步根据创建结果去判断有没有实例正在运行。但是要注意一个点,在软件退出的时候,需要将软件启动时创建的互斥对象销毁掉。

代码
    HANDLE m_had = CreateMutex(NULL, TRUE, name.toStdWString().c_str());
    if (GetLastError() == ERROR_ALREADY_EXISTS){
        return false;
    }
    else{
        return true;
    }

	// 解锁
    if (m_had != NULL)
    {
        ret = CloseHandle(m_had);
        if (ret)
        {
            m_had = NULL;
        }
    }

直接检测进程名称

当然,要实现这种需求最简单的就是直接检测进程的运行。以Windows下的应用程序拓展名(exe)为例:

bool checkProcessRunning(const QString& processName, QList<quint64>& listProcessId)
{
	bool res = false;
	HANDLE    hToolHelp32Snapshot;
	hToolHelp32Snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
	PROCESSENTRY32    pe = { sizeof(PROCESSENTRY32) };
	BOOL  isSuccess = Process32First(hToolHelp32Snapshot, &pe);
	while (isSuccess)
	{
		size_t len = WideCharToMultiByte(CP_ACP, 0, pe.szExeFile, wcslen(pe.szExeFile), NULL, 0, NULL, NULL);
		char* des = (char*)malloc(sizeof(char) * (len + 1));
		WideCharToMultiByte(CP_ACP, 0, pe.szExeFile, wcslen(pe.szExeFile), des, len, NULL, NULL);
		des[len] = '\0';
		if (!strcmp(des, processName.toStdString().c_str()))
		{
			listProcessId.append(pe.th32ProcessID);
			res = true;
		}
		free(des);
		isSuccess = Process32Next(hToolHelp32Snapshot, &pe);
	}
	CloseHandle(hToolHelp32Snapshot);
	return res;
}

通用方案

对于需要跨平台开发的同学们,上面说的系统API就没办法满足一套代码就可以实现需求。所以下面介绍一些使用Qt封装的一些上层接口的方法。

QLocalServer + QLocalSocket

通过启动一个本地的socket服务,当软件启动时,连接对应的socket服务,根据服务的连接情况,来确定是否已经有实例运行了。

// 创建socket,连接服务
QLocalSocket socket;
socket.connectToServer("server_name", QIODevice::WriteOnly);
if (socket.waitForConnected(500)) {
    // 代表有实例已经运行
    return;
}

// 如果没有实例运行,则创建QLocalServer
m_pLocalServer = new QLocalServer();

if (!localServer.listen("server_name")){
    // 监听失败处理
}

QSharedMemory

在软件运行时,绑定到指定的共享内存中,如果共享内存不存在,则附加成功,也就意味着当前没有程序正在运行。反之,则代表程序正在运行。

//通过共享内存,让程序只产生一个运行实例
QSharedMemory sharedMemory("xxx");
if (sharedMemory.attach(QSharedMemory::ReadOnly))
{
    //已创建有共享内存
    return 0;
}
//创建共享内存,空间大小为1字节
sharedMemory.create(1);

总结

看到这里,不难发现,除了直接获取进程是否存在,其余实现需求的方法归根结底就是一个路子:
进程间通信。 所以只要能够实现进程间通信的方法,都可以用来实现这个需求,哪怕是 RPC。

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

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

相关文章

Android广播机制

简介 某个网络的IP范围是192.168.0.XXX&#xff0c;子网 掩码是255.255.255.0&#xff0c;那么这个网络的广播地址就是192.168.0.255。广播数据包会被发送到同一 网络上的所有端口&#xff0c;这样在该网络中的每台主机都将会收到这条广播。为了便于进行系统级别的消息通知&…

Android使用http加载自建服务器静态网页

最终效果如下图&#xff0c;成功加载了电脑端的静态网页内容&#xff0c;这是一个xml文件。 电脑端搭建http服务器 使用“Apache Http Server”&#xff0c;下载地址是&#xff1a;https://httpd.apache.org/download.cgi。具体操作步骤&#xff0c;参考&#xff1a;Apache …

使用 urllib OpenSSL 时遇到的问题及解决

题意&#xff1a; ImportError: urllib3 v2.0 only supports OpenSSL 1.1.1, currently the ssl module is compiled with LibreSSL 2.8.3 当前使用的 urllib3 版本&#xff08;v2.0&#xff09;仅支持 OpenSSL 1.1.1 或更高版本&#xff0c;但你的 Python 环境中的 ssl 模块…

Windows 11 安装 Python 3.11 完整教程

Windows 11 安装 Python 3.11 完整教程 一、安装包安装 1. 下载 Python 3.11 安装包 打开浏览器,访问 Python 官方下载页面。点击“Download Python 3.11”,下载适用于 Windows 的安装包(Windows installer)。 2. 安装 Python 3.11 运行下载的安装包 python-3.11.x-amd6…

django @login_required 为什么会自动重定向到/accounts/login/?next=/myblog/post/new/

在Django中&#xff0c;login_required 装饰器用于确保用户在访问某个视图时已经登录。如果用户未登录&#xff0c;那么Django会自动重定向用户到登录页面。默认情况下&#xff0c;Django使用/accounts/login/作为登录URL。如果用户试图访问一个需要登录的视图&#xff0c;比如…

eNSP-VLAN虚拟局域网

一、出现Vlan的原因 同一个局域网&#xff0c;使用交换机连接&#xff0c;虽然比集线器相连&#xff0c;降低了广播风暴&#xff0c;但是局域网主机数量够多的时候&#xff0c;正常的广播数据(arp、dhcp)也很影响网络性能&#xff0c;所以还需要进一步降低广播风暴——VLAN (图…

Altium Designer专业PCB设计软件下载安装 Altium Designer安装包下载获取

在电子设计的广袤领域中&#xff0c;PCB设计无疑占据着重要的地位。而Altium Designer作为一款业界领先的电子设计自动化软件&#xff0c;其提供的先进布局工具&#xff0c;无疑为设计师们打开了一扇通往高效、精确设计的大门。 在PCB设计的核心环节——布局中&#xff0c;Alti…

xinput1_4.dll丢失怎么办?如何来解决xinput1_4.dll丢失问题

在电脑启动游戏时候经常会出现一些问题导致游戏无法打开运行&#xff0c;其中找不到xinput1_4.dll文件丢失就是常见问题之一&#xff0c;那么当遇到xinput1_4.dll丢失怎么办呢&#xff1f;今天就教大家如何来解决xinput1_4.dll丢失问题。 一、xinput1_4.dll文件详解 XINPUT1_4…

一款优秀、亮眼的开源堡垒机

介绍 在运维的日常工作中&#xff0c;登陆服务器操作不可避免&#xff0c;为了更安全的管控服务器&#xff0c;但凡有点规模的公司都会上线堡垒机系统&#xff0c;堡垒机能够做到事前授权、事中监控、事后审计&#xff0c;同时也可以满足等保合规要求。 提到堡垒机&#xff0…

小白 | 华为云docker设置镜像加速器

一、操作场景 通过docker pull命令下载镜像中心的公有镜像时&#xff0c;往往会因为网络原因而需要很长时间&#xff0c;甚至可能因超时而下载失败。为此&#xff0c;容器镜像服务提供了镜像下载加速功能&#xff0c;帮助您获得更快的下载体验。 二、约束与限制 构建镜像的客…

LVS+Nginx高可用集群--基础篇

1.集群概述 单体部署&#xff1a; 可以将上面内容分别部署在不同的服务器上。 单体架构的优点&#xff1a; 小团队成型就可完成开发&#xff0c;测试&#xff0c;上线 迭代周期短&#xff0c;速度快 打包方便&#xff0c;运维简单 单体架构的挑战&#xff1a;单节点宕机造成…

SecureCRT--使用sftp上传和下载文件

原文网址&#xff1a;SecureCRT--使用sftp上传和下载文件_IT利刃出鞘的博客-CSDN博客 简介 本文介绍SecureCRT如何在软件内直接上传和下载文件。 SecureCRT可以用如下两种方法上传和下载文件&#xff1a; 自带的sftp插件服务器安装rz/sz命令 本文介绍第一种方法&#xff0…

12个视觉艺术分类

视觉设计可以按照多种方式进行分类&#xff0c;这些分类通常基于设计的目的、风格或应用场景。本文为大家介绍12种视觉设计&#xff0c;分别是平面设计、标志设计、包装设计、用户界面设计 (UI Design)、用户体验设计 (UX Design)、插图设计、网页设计、动画设计、展览设计、环…

Jenkins 下使用 Node 和 Npm(借助 nvm-wrapper 插件)构建前端程序

一、前言 搭建完Jenkins后&#xff0c;如何使用node进行构建前端呢&#xff0c;多个项目会使用的node的多个版本。如何动态指定node的版本进行构建呢。 方案一&#xff1a; 安装多个node版本&#xff0c;然后进行指定。这样比较麻烦。 方案二&#xff1a; 使用Jenkins的nv…

C++时区转换

#include <iostream> #include "cctz/civil_time.h" #include "cctz/time_zone.h"// 时区转换库 // https://github.com/google/cctzint test() {for (cctz::civil_day d(2016, 2, 1); d < cctz::civil_month(2016, 3); d) {std::cout << &…

必备的 Adobe XD 辅助工具

想要高效便捷的使用 Adobe XD&#xff0c; Adobe XD 插件是必不可少的&#xff0c; Adobe XD 的插件非常多&#xff0c;但 90%都是英文&#xff0c;并且良莠不齐。在这儿挑选 9 个好用的 Adobe XD 插件给大家&#xff0c;这里是我整理的一些实用 Adobe XD 插件&#xff0c;让你…

Python基础小知识问答系列-列表元素次数统计

1. 问题&#xff1a; 怎样统计列表中元素出现次数&#xff1f; 怎样获得列表中元素出现次数排在前n的元素&#xff1f; 怎样汇总两个列表中元素出现次数的信息&#xff1f; 2. 解决方法&#xff1a; 使用collections模块中的Counter函数。 示例&#xff1a; i…

[Mysql] 的基础知识和sql 语句.教你速成(下)——数据库的约束篇

目录 前言 约束 一.我们为什么需要约束 二.常见的约束类型 NOT NULL 约束 UNIQUE 约束 DEFAULT 约束 PRIMARY KEY FOREIGN KEY CHECK约束 原因&#xff1a; 结尾 前言 距离上篇的更新已经快两周了,这个时候大伙都已经考完了吧!现在更新多少有点马后炮,但是没办法呀…

Qt:5.QWidget属性介绍(Enabled属性-控件可用性设置、geometry属性-控件位置/大小设置)

目录 一、 QWidget属性的介绍&#xff1a; 二、Enabled属性-控件可用性设置&#xff1a; 2.1Enabled属性的介绍&#xff1a; 2.2获取控件当前可用状态的api——isEnabled()&#xff1a; 2.3设置控件当前的可用状态的api—— setEnabled() &#xff1a; 2.4 实例&#xff…

ARM架构 AArch64 基础知识介绍

介绍 aarch64是 ARM 架构的 64 位版本&#xff0c;它是 ARMv8 架构的一部分&#xff0c;被设计用来提供更高的性能和更大的地址空间&#xff0c;同时保持与 32 位 ARM 架构的兼容性。AArch64 是 ARMv8 的 64 位指令集架构&#xff08;ISA&#xff09;&#xff0c;它提供了丰富的…