在工程文件中, WinMain函数里加上以下代码

  1. HANDLE hMutex = CreateMutex(NULL, false, "Process");
  2. if (GetLastError() == ERROR_ALREADY_EXISTS)
  3. {
  4. CloseHandle(hMutex);
  5. MessageBox(Application->Handle, "程序已经在运行中,不能重复启动!", "提示", MB_OK +MB_ICONWARNING);
  6. Application->Terminate();
  7. return 0;
  8. }
  9. Application->CreateForm(__classid(TForm1), &Form1);

主要使用到CreateMutex()函数和GetLastError()以及一个常量ERROR_ALREADY_EXISTS.

当然, 你的程序有窗体的话, 还可以使用FindWindow().

  1. void *handle = FindWindow(NULL, WindowName.c_str());
  2. if (handle!=NULL)
  3. return 0;

进程的互斥运行

正常情况下,一个进程的运行一般是不会影响到其他正在运行的进程的。但是对于某些有特殊要求的如以独占方式使用串行口等硬件设备的程序就要求在其进程运行期间不允许其他试图使用此端口设备的程序运行的,而且此类程序通常也不允许运行同一个程序的多个实例。这就引出了进程互斥的问题。

实现进程互斥的核心思想比较简单:进程在启动时首先检查当前系统是否已经存在有此进程的实例,如果没有,进程将成功创建并设置标识实例已经存在的标记。此后再创建进程时将会通过该标记而知晓其实例已经存在,从而保证进程在系统中只能存在一个实例。具体可以采取内存映射文件、有名事件量、有名互斥量以及全局共享变量等多种方法来实现。下面就分别对其中具有代表性的有名互斥量和全局共享变量这两种方法进行介绍:

  1. // 创建互斥量
  2. HANDLE m_hMutex = CreateMutex(NULL, FALSE, "Sample07");
  3. // 检查错误代码
  4. if (GetLastError() == ERROR_ALREADY_EXISTS) {
  5.  // 如果已有互斥量存在则释放句柄并复位互斥量
  6.  CloseHandle(m_hMutex);
  7.  m_hMutex = NULL;
  8.  // 程序退出
  9.  return FALSE;
  10. }

上面这段代码演示了有名互斥量在进程互斥中的用法。代码的核心是CreateMutex()对有名互斥量的创建。CreateMutex()函数可用来创建一个有名或无名的互斥量对象,其函数原型为:

  1. HANDLE CreateMutex(
  2.  LPSECURITY_ATTRIBUTES lpMutexAttributes, // 指向安全属性的指针
  3.  BOOL bInitialOwner, // 初始化互斥对象的所有者
  4.  LPCTSTR lpName // 指向互斥对象名的指针
  5. );

如果函数成功执行,将返回一个互斥量对象的句柄。如果在CreateMutex()执行前已经存在有相同名字的互斥量,函数将返回这个已经存在互斥量的句柄,并且可以通过GetLastError()得到错误代码ERROR_ALREADY_EXIST。可见,通过对错误代码ERROR_ALREADY_EXIST的检测可以实现CreateMutex()对进程的互斥。

建立互斥体,用来同步。如果一个线程获取了互斥体,则要获取该互斥体的第二个线程将被挂起,直到第一个线程释放该互斥体。

参数 
lpMutexAttributes 
指向一个SECURITY_ATTRIBUTES结构的指针,这个结构决定互斥体句柄是否被子进程继承。     
bInitialOwner 
布尔类型,决定互斥体的创建者是否为拥有者 
lpName 
指向互斥体名字字符串的指针。互斥体可以有名字。 
互斥体的好处是可以在进程间共享

心得体会:
    CreateMutex() 用于有独占要求的程序 (在其进程运行期间不允许其他使用此端口设备的程序运行,或不允许同名程序运行)。如有同名程序运行,则通过 GetLastError()得到错误代码 ERROR_ALREADY_EXIST。

刚才又执行了下得出的结果(程序名samp)
       一般情况下:一进入调试阶段,进程管理器中就出现了samp进程,执行到CreateMutex时返回进程句柄,执行到if(GetLastError() == ERROR_ALREADY_EXISTS ) 进行判断时,跳过不执行if中的内容,所以表示没有互斥。
       调试之前先运行debug中的samp.exe再调试:一进入调试阶段,进程管理器中就出现了两个samp进程,执行到CreateMutex时返回进程句柄,执行到if(GetLastError() == ERROR_ALREADY_EXISTS ) 进行判断时,执行if中的内容,表示有互斥

我们公司的使用方法为

  1. HANDLE NetIq::CreateMutexNetIq()
  2. {
  3. HANDLE nMutex = NULL;
  4. std::string strDeployRole = NetClient::Instance().m_strDeployRole;
  5. std::string strMutexId = Utils::String::Format("%s%s", NetIQ::Configure::Instance().m_strGuid.c_str(), strDeployRole.c_str());
  6. nMutex = ::CreateMutex(NULL, FALSE, strMutexId.c_str());
  7. if( NULL != nMutex )
  8. {
  9. DWORD dwErrorCode = ::GetLastError();
  10. if( ERROR_ALREADY_EXISTS == dwErrorCode )
  11. {
  12. __ULOG_INFO(__ULOG_FMT("App", "Mutex (%s) exists"), strMutexId.c_str());
  13. std::string strTitle;
  14. if( !RegisterKey::Instance().Read("", "Title", strTitle) )//读取注册表中的项目窗口名,,以便在以下将其显示。国。
  15. {
  16. return NULL;
  17. }
  18.  
  19. // instance exist
  20. HWND hAppWindow = ::FindWindow(NULL, strTitle.c_str());
  21. if( NULL != hAppWindow )
  22. {
  23. ::ShowWindow(hAppWindow, SW_SHOWNORMAL);
  24. ::SetWindowPos(hAppWindow, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
  25. ::SetWindowPos(hAppWindow, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
  26. }
  27.  
  28. return NULL;
  29. }
  30. }
  31.  
  32. return nMutex;
  33. }

防止程序启动两次的方法CreateMutex()的更多相关文章

  1. QT防止程序启动两次的方法

    为了使QT 能保证只创建一个实例来进行, 对windows和linux分别采取了全局互斥变量和文件锁的方法. Q_OS_WIN32宏用来表示编译运行的目标平台是windows,Q_OS_LINUX则标 ...

  2. Android adb.exe程序启动不起来处理方法

    经常遇到 Please ensure that adb is correctly located at 'D:\java\sdk\platform-tools\adb.exe' and can be ...

  3. 【转】关于Tomcat下项目线程启动两次的问题

    最近遇见了一个很搞得事情,在tomcat下启动项目时自己写的定时程序被执行了两次,导致程序启动了两个线程,使定时任务在几秒间隔内执行了两次,后来通过日志查到,原来是tomcat将项目启动了两次,为什么 ...

  4. 关于Tomcat下项目被启动两次为问题

    最近遇见了一个很搞得事情,在tomcat下启动项目时自己写的定时程序被执行了两次,导致程序启动了两个线程,使定时任务在几秒间隔内执行了两次,后来通过日志查到,原来是tomcat将项目启动了两次,为什么 ...

  5. Qt程序启动画面播放(gif与swf两种动画格式)

    学习Qt有一段时间了,发现一个小问题,网上关于Qt的资料或者总结性的学习及应用文章有点少. 比如,Qt完整的API,程序运行之前的启动画面如何按理想效果播放等,每次想在项目中添加一些应用的时候,总是找 ...

  6. Info.plist和pch文件的作用,UIApplication,iOS程序的启动过程,AppDelegate 方法解释,UIWindow,生命周期方法

    Info.plist常见的设置 建立一个工程后,会在Supporting files文件夹下看到一个“工程名-Info.plist”的文件,该文件对工程做一些运行期的配置,非常重要,不能删除 注:在旧 ...

  7. C#控制台或应用程序中两个多个Main()方法的可行性方案

    大多数初级程序员或学生都认为在C#控制台或应用程序中只能有一个Main()方法.但是事实上是可以有多个Main()方法的. 在C#控制台或应用程序中,在多个类中,且每个类里最多只能存在一个Main() ...

  8. C#控制台或应用程序中两个多个Main()方法的设置

    大多数初级程序员或学生都认为在C#控制台或应用程序中只能有一个Main()方法.但是事实上是可以有多个Main()方法的. 在C#控制台或应用程序中,在多个类中,且每个类里最多只能存在一个Main() ...

  9. SpringBoot图片上传(三)——调用文件上传项目的方法(同时启动两个项目)

    简单说明:图片上传有一个专门的工程A,提供了图片的上传和下载预览,工程B涉及到图片上传以及回显,都是调用的工程A的方法,言外之意就是要同时启动两个项目. 代码: //工程B的html代码 <di ...

随机推荐

  1. Wpf Hyperlink超链接控件使用

    一.在Windows窗口中使用 1.点击链接使用系统默认游览器打开 <TextBlock Margin="10,20,-10,-20"> 默认: <Hyperli ...

  2. 使用WebUploader使用,及使用后测试横拍或竖拍图片图片方向不对等解决方案

    WebUploader是由Baidu WebFE(FEX)团队开发的一个简单的以HTML5为主,FLASH为辅的现代文件上传组件.在现代的浏览器里面能充分发挥HTML5的优势,同时又不摒弃主流IE浏览 ...

  3. SxsTrace工具使用方法(转)

    http://blog.sina.com.cn/s/blog_494e45fe0102dtt3.html Windows7平台上有一个强大的SxsTrace工具,可以跟踪调试应用程序运行时需要的动态库 ...

  4. 2D简单图形相关算法罗列

    因为平常在Qt开发过程中经常会与一些简单的2D几何图形打交道,因此学习和掌握一些基本的2D几何计算还是很有必要的,在这里罗列一些常用的基本情况,之后会适时补充. [1] 两点之间距离,根据两个点的差值 ...

  5. SQL Server 2008连接字符串写法大全(摘自网络)

    一..NET Framework Data Provider for SQL Server 类型:.NET Framework类库使用:System.Data.SqlClient.SqlConnect ...

  6. Flowplayer-一款免费的WEB视频播放器 转 - helloweba.com

    Flowplayer支持播放flv.swf等流媒体以及图片文件,能够非常流畅的播放视频文件,支持自定义配置和扩展. 1.加载flowplayer.js 在要播放视频的页面的head之间加入flowpl ...

  7. Centos6.x 64位 安装JDK

    JDK下载地址: http://www.oracle.com/technetwork/cn/java/javase/downloads/jdk7-downloads-1880260-zhs.html ...

  8. Installshield更新时,新加dll未拷贝至安装目录问题完美解决【原创】

    最近在发现在开发过程中新增的目录或文件(特别是dll\ocx\exe等二进制文件),在升级安装时拷贝失败. 经过一周的研究,完美解决办法: 对于新增的文件或目录,放到一个新的component中,并且 ...

  9. 【HDOJ】1438 钥匙计数之一

    状态压缩.分最后一个槽的值以及当前的配置方案是否可以进行DP. /* 1438 */ #include <cstdio> #include <cstring> #include ...

  10. POJ3687 Labeling Balls(拓扑)

    题目链接. 题目大意: N个球,从1-N编号,质量不同,范围1-N,无重复.给出小球间的质量关系(<), 要求给每个球贴标签,标签表示每个球的质量.按编号输出每个球的标签.如果解不唯一,按编号小 ...