赞助

VC 实现程序只运行一个实例,并激活已运行的程序

转载:http://blog.sina.com.cn/s/blog_4b44e1c00100bh69.html

 

进程的互斥运行:CreateMutex函数实现只运行一个程序实例

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

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

 // 创建互斥量
 HANDLE m_hMutex = CreateMutex(NULL, FALSE, "Sample07");
 // 检查错误代码

 // 如果程序已经存在并且正在运行
 if (GetLastError() == ERROR_ALREADY_EXISTS)

 {
   // 如果已有互斥量存在则释放句柄并复位互斥量
  CloseHandle(m_hMutex);
  m_hMutex = NULL;
  // 程序退出
  return FALSE;
 }

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

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

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

建立互斥体,用来同步。如果一个线程获取了互斥体,则要获取该互斥体的第二个线程将被挂起,直到第一个线程释放该互斥体。  
  参数  
  lpMutexAttributes    
  指向一个SECURITY_ATTRIBUTES结构的指针,这个结构决定互斥体句柄是否被子进程继承。     
  bInitialOwner 
  布尔类型,决定互斥体的创建者是否为拥有者  
  lpName    
  指向互斥体名字字符串的指针。互斥体可以有名字。  
  互斥体的好处是可以在进程间共享

 

将 CreateMutex 代码加到  ****App::InitInstance() 函数中即可实现只运行一个实例的效果。

以上文章转载自:我的程序员生涯 http://steveq.blog.sohu.com/71112121.html

 

通过上面文章我们知道:使用CreateMutex可以防止一个实例多次运行。

下面介绍如何实现当再次运行程序时如何激活已经运行的程序,比如此程序只是已被最小化。

方法如下:

 

 1 BOOL C**App::InitInstance()
 2 {
 3 
 4  //创建进程互斥体Sample07
 5  m_hMutex = CreateMutex(NULL,TRUE,_T("Sample07"));
 6 
 7  if (m_hMutex == NULL)
 8  {
 9   return FALSE;
10  }
11 
12  //如果程序已经存在并且正在运行
13  if (GetLastError() == ERROR_ALREADY_EXISTS)
14  {
15 
16   HWND hProgramWnd = ::FindWindow(NULL,L"Sample07");
17   if (hProgramWnd)
18   {
19    WINDOWPLACEMENT* pWndpl = NULL;
20 
21    WINDOWPLACEMENT   wpm; 
22    pWndpl =&wpm;
23    GetWindowPlacement(hProgramWnd,&wpm);
24    if (pWndpl)
25    {
26     //将运行的程序窗口还原成正常状态
27     pWndpl->showCmd = SW_SHOWNORMAL;
28     ::SetWindowPlacement(hProgramWnd,pWndpl);
29     SetWindowPos(hProgramWnd,HWND_NOTOPMOST,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE);
30     FlashWindow(hProgramWnd,TRUE);//任务栏图标闪烁
31    }
32 
33   }
34   //关闭进程互斥体
35 
36   CloseHandle(m_hMutex);
37   m_hMutex = NULL;
38   return FALSE;
39  }
40 }

 

posted @ 2016-02-18 10:47  车臣  阅读(2349)  评论(0编辑  收藏  举报