只能同时运行一个实例的程序

很多情况下,程序会要求同一时间内只能运行一个实例,以免发生系统崩溃、数据遭破坏等后果。最常用被使用的是创建一个有名字的Mutex(互斥)的方法。程序的实例或对象含有Mutex之后,同一时间内将只能被一个线程访问。

Windows给我们提供了CreateMutex函数来创建Mutex。原型如下:

HANDLE WINAPI CreateMutex(
  __in_opt  LPSECURITY_ATTRIBUTES lpMutexAttributes,
  __in      BOOL bInitialOwner,//Mutex的所有者的句柄。
  __in_opt  LPCTSTR lpName//Mutex对象的名称。
);

我们为互斥体起一个名字,作为CreateMutex的第三个参数。那么程序运行时,将使用CreateMutex创建一个互斥体,再次运行将再创建一个同名的互斥体从而引发错误信息,此时GetLastError函数将返回ERROR_ALREADY_EXISTS错误信息。

利用这一点,我们可以达到只让程序运行一个实例的目的。代码如下。

 1 #include <windows.h>
 2 #include <tchar.h>
 3 int _stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCMD)
 4 {
 5  CreateMutex(NULL,FALSE,_T("Mutex"));
 6  if(GetLastError()==ERROR_ALREADY_EXISTS)
 7   return FALSE;
 8  MessageBox(NULL,_T("Program Success !"),_T("Mutex"),MB_OK);
 9  return 0;
10 }

但这样并不完善。当用户想要运行该程序时,如果已经有实例正在运行,最好能激活运行中实例的窗口,如果该窗口处于最小化则将其弹出

 1 BOOL MyMUTEX()
 2 {
 3  //1、创建Mutex
 4  HANDLE hMutex=CreateMutex(NULL,TRUE,_T("Mutex"));
 5  if (hMutex == NULL)
 6  {
 7   return FALSE;
 8  }
 9  //2、如果Mutex已经存在并且正在运行
10  if (GetLastError() == ERROR_ALREADY_EXISTS)
11  {
12   //3、获取窗口名称
13   HWND hProgramWnd =FindWindow(NULL,_T("WindowsName"));
14   if (hProgramWnd)
15   {
16    WINDOWPLACEMENT* pWndpl = NULL;
17    WINDOWPLACEMENT   wpm;
18
19    GetWindowPlacement(hProgramWnd,&wpm);
20    pWndpl =&wpm;
21    if (pWndpl)
22    {
23     //4、将运行的程序窗口还原成正常状态
24     pWndpl->showCmd = SW_SHOWNORMAL;
25     SetWindowPlacement(hProgramWnd,pWndpl);
26     SetWindowPos(hProgramWnd,HWND_NOTOPMOST,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE);
27     //激活窗口
28     SetForegroundWindow(hProgramWnd);
29    }
30   }
31   //6、关闭进程互斥体
32   CloseHandle(hMutex);
33   hMutex = NULL;
34   return FALSE;
35  }
36  return TRUE;
37 }

也可以使用下面这种更为简短的代码。但不知为什么,在我的电脑上运行时,感觉上面这段代码比下面代码的运行速度要快很多。

 1 BOOL MyMUTEX()
 2 {
 3  HANDLE hMutex=CreateMutex(NULL,TRUE,_T("Mutex"));
 4  if (hMutex == NULL)
 5  {
 6   return FALSE;
 7  }
 8  if (GetLastError() == ERROR_ALREADY_EXISTS)
 9  {
10   HWND hProgramWnd =FindWindow(NULL,_T("WindowsName"));
11   ShowWindow(hProgramWnd,SW_RESTORE);
12   SetForegroundWindow(hProgramWnd);
13
14   CloseHandle(hMutex);
15   hMutex = NULL;
16   return FALSE;
17  }
18  return TRUE;
19 }
时间: 2024-10-09 21:05:43

只能同时运行一个实例的程序的相关文章

vc++高级班之窗口篇[4]---让程序只运行一个实例

大家都看过或者使用过类似只运行一个实例的程序,比如:QQ游戏.部分浏览器 等等! 让一个程序只运行一个实例的方法有多种,但是原理都类似,也就是在程序创建后,有窗口的程序在窗口创建前, 检查系统中是否已经设置了某些特定标志,是否创建了一些全局唯一的东西,或者让程序的多个实例都能看到的东西, 如果有则说明已经有一个实例在运行了,则当前程序通知用户如何如何,然后程序退出,当然方法有很多种,各有各的优缺点! ①.创建互斥体 Mutex 法: 但是单纯的使用互斥体的话不能取得已经创建的实例窗口局柄,因此无

WinForm限制客户程序只能运行一个实例

WinForm限制客户程序只能运行一个实例: using System; using System.Threading; static void Main() { bool create = false; using (Mutex mu = new Mutex(true, Application.ProductName, out create)) { if (create) { Application.Run( new MainForm() ); } else { MessageBox.Show

C#让应用程序只运行一个实例的几种方法

一 判断是否有相同的实例已经运行 1 根据“Mutex”判断是否有相同的实例在运行 /// <returns>已有实例运行返回true,否则为false</returns>public bool IsRunningProcessByMutex(){     bool createNew;     using (System.Threading.Mutex mutex = new System.Threading.Mutex(true, Application.ProductName

C#程序只允许运行一个实例的解决方案

最近在做winform的程序中,需要只能打开一个程序,如果已经存在,则激活该程序的窗口,并显示在最前端.在网上google了一哈,找到了很多的解决方案.这里我整理了3种方案,并经过了测试,现和朋友们分享: 一.使用用互斥量(System.Threading.Mutex) 同步基元,它只向一个线程授予对共享资源的独占访问权.在程序启动时候,请求一个互斥体,如果能获取对指定互斥的访问权,就职运行一个实例. 代码 bool createNew;            using (System.Thr

C# WinForm 判断程序是否已经在运行,且只允许运行一个实例

static class Program {   /// <summary>   /// 应用程序的主入口点.   /// </summary>   [STAThread]   static void Main()   {     Application.EnableVisualStyles();     Application.SetCompatibleTextRenderingDefault(false);     //1.这里判定是否已经有实例在运行     //只运行一个实

【转】delphi程序只允许运行一个实例的三种方法:

一.        创建互斥对象 在工程project1.dpr中创建互斥对象 Program project1 Uses Windows,Form, FrmMain in 'FrmMain.pas' {MainForm}; {$R *.res} var hAppMutex: THandle; //声明互斥变量 begin hAppMutex := CreateMutex(nil, false,’projectname’); //创建互斥对象projectname工程名称 if ( (hAppM

C#应用程序只允许运行一个实例,多次运行的时候激活当前实例,显示其界面

很多时候,我们开发的程序,需要单例运行的的功能,即整个应用程序只允许同时运行最多一个实例,重复运行的时候,激活当前实力,显示其界面. 在C#程序中,其解决方案有多重,可以参照Charles Chen 的C#程序只允许运行一个实例的解决方案一文. 参照其文章,我决定使用调用Windows Api的方法,大致如下: namespace BarCodeSystem { public static class Program { /// <summary> /// Application Entry

逆向学习XX客户端如何只运行一个实例

个人认为学习分两种, 一种是当面请教和直接从书本网络中的资料学习. 其二就是看着令你惊叹的作品-顿悟. 什么?顿悟不了?那我们就一起来逆向学习吧!差点忘了,我并不打算提供Demo,这并不重要,难道你打算遇到一个相同的情景?重在方法. 注意: 本文为了照顾新手人群,对于某些内容可能会非常详细的推演. 名词解释: 一个实例:一个对象,这里指一个程序被创建后在内存中的数量.大白话就是:成功运行了几次. 事由: 今天闲来无事(忙里偷闲)运行了两次Dr_COM的宽带认证客户端.如咱所料, 如图: 我们知道

只运行一个实例以及内存泄漏检测

unit 使应用程序只运行一个实例; interface uses Windows; const  // - 互斥体唯一的名字  _Mutex_Name = '{19631971-1976-1981-1989-199319941995}'; var  _Mutex_Handle: THandle; implementation initialization // - 载入时调用的代码 // - 创建互斥体对象_Mutex_Handle := CreateMutex(nil, False, LPC