防止C++程序重复运行的几种方法

C++防止头文件被重复引入的3种方法! 在之前我们详细介绍了 C 语言中如何使用宏定义(#ifndef / #define / #endif)来有效避免头文件被重复 #include,此方式在 C++ 多文件编程中也很常用。 举个例子,如下是一个 C++ 项目,其内部含有 school.h 和 student.h 这 2 个头文件以及 main.cpp 源文件,其各自包含的代码为: //student.h class Student { //...... }; //school.h #include "student.h" class S 阅读详情
 

防止C++程序重复运行的几种方法

有时候,为了某些要求,我们希望程序实例只运行一次。而在VB6中,我们可以很轻易的根据App.hPreInstance来判断程序是否已经运行。但是在C++中,这一切就变得不是那么容易。

  虽然WinMain函数有hPreInstance参数来指示,但是那是在Win16位的前提下,到了32Bit时代,那个参数已经完全成为摆设。

  而本文正好探讨了如何防止C++程序重复运行的方法。

  PS:因为本人使用MFC,所以为了方便,所有代码均为以MFC为基础。大家可以根据自己需要更改

  1.查找窗体

  对于存在GUI窗体(CUI暂不讨论)的程序来说,最容易想到的就是利用FindWindow,以标题作为参数进行查找主窗体,然后使其关闭即可。

  通常,我们能写出如下代码:

// Find Window by Caption
// Add this code in InitInstance function of class
// you have derived from the CWinApp class

HWND hWnd = ::FindWindow(NULL, "MFCDialog");

if (hWnd)
{
  
AfxMessageBox("Has been running");
  
return FALSE;
}
以上的代码可以简单的起到防止重复启动的效果,但是局限性很大。

首先,由于在FindWindow中要指定窗体的标题,如果窗体的标题在程序运行中是不断变化的,那么就给搜索带来了一定难度。

  而且,如果其他程序也恰好是用相同的标题的话……- -#。当然,你可以通过在FindWindow中指定类名来减少错误。但是如果你看过我前面写的文章的话,你就会发现,MFC注册窗口类并不是那么随意,而是经过N次阴谋筹划之后……

  看来这方法的局限性的确很大- -#

  2.额外窗体存储

  此方法来源于对上面一种方法的补充,因为通过搜索MFC的窗体类比较困难,而且准确度不一定高。所以,我想到了使用额外窗体存储(Extra Widnow Memory)的方法

  PS:关于什么是额外窗体存储,请自行google或MSDN或查看我曾经写的The Analyses Of Windows Runnning Principle

  如果你使用SDK进行开发,可以在创建窗体时填充这一属性,然后用GetWindowLong获取。

  而由于我使用MFC,所以我更关注如何在MFC中使用这一属性。

  一般来说,我们可以使用SetWindowLong对额外窗体存储进行填充,然后用GetWindowLong获取,最后配合FindWindow来检验程序是否重复运行。

引用:
// Add this code in InitDialog function
  // and you can specify any number you want
  
BOOL bRet = ::SetWindowLong(GetSafeHwnd(), GWL_USERDATA, 256);
  
  
// Add this code in InitInstance function
  // Find Window by using extra memory

  
HWND hWnd = FindWindow(NULL, "MFCDialog");
  
  
if (hWnd)
  {
   
BOOL bRet = ::GetWindowLong(hWnd, GWL_USERDATA);

   
if (256 == bRet)  // compare
   
{
      
AfxMessageBox("Has been running");
      
return FALSE;
    }
  }

  3.全局原子

  你可以使用GlobalAddAtom将某个特定的字符串添加到全局原子列表(Global Atom Table),然后在程序运行时检查该字符串即可。

  但是这个方法有一个致命的弱点,程序退出时,Windows不会自动为你删除添加到列表中的Atom,而是需要你自己使用GlobalDeleteAtom进行删除。

  这就意味着,如果你的程序意外的退出了,没有删除添加的Atom,那么,你的程序将无法运行。

  所以,这并不是一个好方法。


  4.枚举进程

  这或许是一个毕竟正常,或者说相对稳定的方法。

  我们可以使用CreateToolhelp32Snapshot或者EnumProcess来枚举当前的进程,然后检查是否已经运行。如果担心存在同名的进程,还可以检查路径。

  枚举进程的代码我之前已经写过,在这里就不再重复了。

  PS:在Vista下使用EnumProcess时,要注意权限问题,OpenProcess增加了一个新的权限常数,仅限Vista。如果不增加这个参数,很多进程是无法被枚举出来的(不过MS不印象我们自己的进程- -#)。


  5.互斥对象

  使用互斥对象来防止程序重复运行是一个很常用的做法,而且M$也推荐使用这种方法。和上面的几种方法相比,需要写的代码少,而且效率比较高。所谓方便易用~

  一般我们会使用CreateMutex来创建互斥体,当第二次创建相同的互斥体时,这个API会返回前一个互斥体的Handle,而GetLastError则会返回ERROR_ALREADY_EXITS

引用:
// Mutex Object
  // Add this code in InistInstance function
  
  
HANDLE hMutex = NULL;
  
TCHAR *lpszName = "TestMutex";

  
hMutex = ::CreateMutex(NULL, FALSE, lpszName);
  
DWORD dwRet = ::GetLastError();

  
if (hMutex)
  {
   
if (ERROR_ALREADY_EXISTS == dwRet)
    {
      
AfxMessageBox("Has been running");
      
CloseHandle(hMutex);  // should be closed
      
return FALSE;
    }
  }
  
else
  
{
   
AfxMessageBox("Create Mutex Error");
  }

  
// Add this code in Destruction function
  
  
::CloseHandle(hMutex);

使用互斥体时要注意几个问题:
  在CreateMutex之后马上GetLastError,GetLastError是一个很复杂的API,任何牵涉到GetLastError的操作在执行之后,都会覆盖先前的值。

  把正常的CloseHandle写到窗体的析构函数或者程序对象的析构函数里。不要在CreateMutex之后立刻CloseHandle,否则互斥对象会被清空。

这也是我当初所犯的错误,(不知道网上那么多错误的代码是不是经过Debug的囧),当互斥对象的最后一个Handle被Close之后,互斥对象将被删除。如果程序在退出时没有清空互斥对象,Windows将会执行这一操作。当然,把次操作交给OS不是一个好习惯。

详情请看MSDN的引用:

引用:
Use the CloseHandle function to close the handle. The system closes the handle automatically when the process terminates. The mutex object is destroyed when its last handle has been closed.

VC_C++如何防止程序同时启动多次 立即下载

相关推荐

程序只能运行一次,防止程序重复执行。

让程序在不同地点只能运行一次。 防止程序重复执行。

【小沐学C++】C++ 禁止程序重复运行

本节内容1、使用内核对象2、使用共享数据段3、使用信号量(Semaphore)4、使用事件Event后记 1、使用内核对象 因为内核对象是可以跨进程存在的,因此我们可以通过创建一个命名互斥体(Mutex)内核对象来判断,当用同一个名字的来创建Mutex时,CreateMutex会返回一个指向该互斥体的句柄,但是GetLastError会得到ERROR_ALREADY_EXISTS的返值。因此我们就可以判断程序已有一个实例在运行。 m_hmutex = ::CreateMutex( NULL,FALSE,ap

爱看书的小沐 2791

从理论到实践:使用Sigrity SystemSI完成DDR4信号完整性仿真全流程解析

本文详细解析了使用Sigrity SystemSI完成DDR4信号完整性仿真的全流程,从核心挑战到实战操作。文章深入探讨了DDR4信号完整性问题,介绍了SystemSI工具链的演进与分工,并提供了从前期准备到高级技巧的详细指南,帮助工程师有效解决DDR4设计中的信号完整性问题。

weixin_30505225的博客 512

C++ 运行单个实例,防止程序多次启动

利用内核对象 封装的类,使用运行单个实例,防止多次启动Demo 例子下载地址:http://pan.baidu.com/share/link?shareid=3202369154&uk=3037189616 //File Name: Singleton.h #pragma once class Singleton { private: ...

weixin_30398227的博客 347

基于vue2的echarts3D地球

采用vue2+js实现了echarts3D地球的放大、缩小和旋转

qq_44699269的博客 1132

ArcGIS符号库下载 | 制图规范、三调、1:1万地形图、土地利用总体规划图.....

最近整理了一些符号库 涉及的类型比较多 包含有三调的(二调的也加上去了),一些点线面符号库,1:1万地形图,1:5万土地利用,土地利用总体规划图

qq_43173805的博客 2万+

(转)防止程序启动两次的方法

方法一 在工程文件中, WinMain函数里加上以下代码(此代码在BCB6.0下运行):HANDLE hMutex = CreateMutex(NULL, false, "Process");         if (GetLastError() == ERROR_ALREADY_EXISTS)         {            CloseHandle(hMutex);    

张奇的专栏 1547

TC3xx芯片中断配置避坑指南:从AUTOSAR Davinci配置到SRN地址计算的完整流程

本文详细解析了英飞凌TC3xx芯片的中断配置流程,从AUTOSAR Davinci工具链到硬件调试的全链路指南。重点介绍了中断路由(IR)模块、服务请求节点(SRN)和中断控制单元(ICU)的配置技巧,帮助开发者避开常见陷阱,优化中断性能。

weixin_30628801的博客 414

C++Qt防止程序重复启动

C++Qt防止程序重复启动

qq_40135848的博客 519

解锁RK3588:内核模块签名与安全启动配置全攻略

RK3588作为一款高性能嵌入式SoC芯片,其内核模块签名与安全启动配置是保障系统安全的核心机制。本文详细介绍了RK3588的芯片特性,重点阐述了安全启动的硬件信任链原理和内核模块签名的实现方法。通过具体步骤演示了从密钥生成、模块签名到验证加载的完整流程,并深入解析了安全启动配置的硬件连接、软件工具准备、密钥烧录等关键环节。此外,还提出了防御旁路攻击和动态信任链扩展等高级安全策略,为RK3588在工业控制、智能安防等高安全要求场景中的应用提供了全面的安全解决方案。

远程部署调试 运行安装 项目调试 二次开发 项目技术新 持续迭代 部分源码免费分享 348

vue3+ts+elementui-plus二次封装树形表格实现不同层级展开收起的功能

我只定义了三层数据,就只演示展开了三层,还可以多层,自己设置即可。

蜗牛~~ 2603

防止C++程序重复打开

我们有些程序是可以同时运行多个进程,典型的像Visual Studio.但有些就能一次运行一个进程.比如Outlook.那你可能会问啥时可以让它同时打开多个应用程序,啥时只能一个啊.这个主要看进程间是否独立,会不会有冲突,是否会时读写相同的文件. 如果你不写代码去做些处理默认肯定是可以让你同时运行多个进程的.那假如只能一次运行一个进程咋整呢?有两种常用的方式.   使用互斥(Mutex) ...

weiwenhp 7847

uniapp - 应用软件在运行时,未见向用户告知权限申请的目的,向用户索取(存储、相机、电话)等权限,不符合华为应用市场审核标准(uniApp开发安卓APP上架应用市场审核被拒绝驳回,详细解决方案)

uniApp应用软件在运行时,未见向用户告知权限申请的目的,向用户索取(存储、相机、电话)等权限,不符合华为应用市场审核标准。uniapp vue2 vue3解决软件在运行时,未见向用户告知权限申请的目的,华为等上架被拒问题,关于华为应用市场上架需要同步告知使用权限的解决方案,uniApp应用软件在运行时,不符合华为应用市场审核标准。解决方案合集!app上架-您的应用在运行时,未同步告知权限申请的使用目的,向用户索取(相机)等权限,不符合华为应用市场审核标准。华为应用市场审核新规(未同步告知权限申请的使用目

🏆 前端领域优质创作者 4165

防止程序重复运行的几种方法

原来的网址:http://hi.baidu.com/dreamyguy/item/555f197bc66db73f704423ef 防止C++程序重复运行的几种方法 有时候,为了某些要求,我们希望程序实例只运行一次。而在VB6中,我们可以很轻易的根据App.hPreInstance来判断程序是否已经运行。但是在C++中,这一切就变得不是那么容易。 虽然WinMain函数有hP

876

【AUTOSAR-E2E】-2.1-配置E2E:基于E2EPW配置一个RX接收的Signal Group(使用E2E Profile 2)

《共13页精讲》:此法也适用于E2E Profile 4/5/6/7/11/22 目录 1 检查CAN Matrix Arxml/DBC是否满足E2E需求 2 在DaVinci Developer中为Port添加E2E保护 3 在DaVinci Configurator settings设置 4 如何使用应用层的E2E保护 5 结尾 <--返回「Autosar_BSW高阶配置」总目录--> <--返回「Autosar_BSW高阶配置」专栏主页--> <--

「汽车电子助手」的博客 4419

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

C++ QT PC端 防止程序重复启动的几种方式

在做客户端的过程中,我们通常会希望程序实例只运行一次,也就是只希望同时启动一个程序。所以今天就总结一下几种防止程序重复启动的方式: 1.使用QT中的QLockFile: QLockFile 使用文件提供在不同的进程间的锁。锁文件可以放置多个进程同时访问同一资源。例如磁盘上的配置文件、套接字、端口、共享内存区域等。使用的时候trylock()对资源进行上锁。当程序运行的时候,上锁成功后,会自动...

漫步繁华街的专栏 2万+

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

在C/C++中防止头文件重复包含的几种方式

在 C/C++ 编程中,头文件的重复包含会导致一系列的问题,如符号重定义、编译错误等。因此,防止头文件的重复包含是至关重要的。下面是几种常见的防止头文件重复包含的方式,并对其做了相关分析和使用建议。 博主在实际开发中一般采用第一种宏定义防护来规避头文件重复包含问题。

crr411422的博客 4610

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

【C++】C++中防止头文件重复包含的两种方法

文章目录01、错误分析:类型重定义(头文件重复包含)02、解决方案2.1、微软宏2.2、条件编译2.3、两种方法比较03、变量被重复包含3.1、解决办法04、版权声明&总结 01、错误分析:类型重定义(头文件重复包含) 现象: #include文件的一 个不利之处在于一个头文件可能会被多次包含,为了说明这种错误,考虑下面的代码: #include "Index.h" #include "Index.h" //当前实际开发中没人会这么写程序,但是我们换一种写法 常犯错误如下: //#inclu

Cain Xcy的博客 6840

C++防止头文件被重复引入的3种方法(详解版)

《防止C语言头文件被重复包含》一节中,详细介绍了 C 语言中如何使用宏定义(#ifndef / #define / #endif)来有效避免头文件被重复 #include,此方式在 C++ 多文件编程中也很常用。 举个例子,如下是一个 C++ 项目,其内部含有 school.h 和 student.h 这 2 个头文件以及 main.cpp 源文件,其各自包含的代码为: //student.h class Student { //...... }; //school.h #inc..

木牛的博客 5797

linux C++ 防止多个程序运行

下面的一段程序可以防止程序被多次重复运行。 原理: 程序运行时会将程序pid保存在一个文件中,             当其它程序运行时,会读取这个pid,并且查看“/proc/[pid]”是否存在;             如果路径存在,说明已有程序在运行,推出, 如果不存在,运行程序 int main(int argc, char* argv[]) { pid_t

fishrain的专栏 1664

C++防止程序重复启动两种方法

C++防止程序重复启动两种方法

doubleintfloat的博客 545
上一篇: 程序员注意:Java开发最容易犯的21种错误(转载)
下一篇: Java中equals和==的区别
findingpan
博客等级 码龄18年 6粉丝 1原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值