Windows下C++防止進程多開

1. 概念

防止進程多開,一般是特指防止同一個exe進程重複打開。爲什麼要防止進程多開呢?

  1. 功能設計上不讓用戶打開兩次,如各種遊戲客戶端。
  2. 防止多進程對資源訪問的衝突。如當前進程對某文件可能在進行寫讀操作,再打開新進程時可能的寫讀操作會導致出現文件訪問異常甚至崩潰。

2. 方法

網上很多資料推薦利用遍歷窗口來判斷,如果找到對應的窗口則認爲進程已經打開。這種方法其實存在很大的風險。

  1. 窗口創建的過程中可能因爲系統消息阻塞導致創建很慢,那麼在窗口創建過程中再打開進程,並通過遍歷窗口來判斷則可能失敗。
  2. 窗口關閉過程中,窗口銷燬了,但是此時主進程以及其他子進程可能由於某些原因(如內存申請較大,釋放較慢等)導致銷燬較慢。在此過程中,再次打開進程,並通過遍歷窗口來判斷則可能失敗。
    推薦用以下兩種方法:

2.1. 通過互斥內核對象

所有的內核對象都是可以跨進程通信的,在此選擇簡單的內核對象互斥量。爲了保證互斥量儘量延後釋放,不建議使用手動調用ReleaseMutex來釋放互斥量對象。操作系統的內核管理器會在進程銷燬後自動釋放所有的內核對象。

BOOL CXXXApp::InitInstance()
{
	HANDLE hObject = ::CreateMutex(NULL,FALSE, _T("MutexDemo"));  
	if(GetLastError() == ERROR_ALREADY_EXISTS)  
	{  
		return FALSE;  
	}
  ......

2.2. 通過共享內存段

除了內核對象外,我們還可以通過編譯鏈接期間指定共享內存段來達到防止進程多開。此方式相比內核對象可能更可靠,因爲內存段的回收是系統管理的,應該是在進程完全銷燬了之後纔回收清空的。

  • 申請共享內存段,段名需要保證唯一性
#pragma data_seg("MutexDemo")
int g_nOnlyOne = 0;
#pragma data_seg()
#pragma comment(linker, "/Section:MutexDemo,RWS")
  • 通過內存段變量進行判斷
BOOL CTestFWApp::InitInstance()
{
	if (1 == g_nOnlyOne)
	{
		return FALSE;
	}
	g_nOnlyOne = 1;
  .......
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章