青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

yehao's Blog

防止C++程序重復運行的幾種方法

轉自http://hi.baidu.com/dreamyguy/blog/item/aacc6f44086afe45500ffef9.html

有時候,為了某些要求,我們希望程序實例只運行一次。而在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來枚舉當前的進程,然后檢查是否已經運行。如果擔心存在同名的進程,還可以檢查路徑。

//   關閉一個進程  
static   bool   CloseApplication(CString   sAppToClose,   CString   sAppToUpdate,    
CString   sFilename,   bool   bAskUser   /*   =   true   */)  
{  
//   Declare   variables  
HANDLE   hProcessSnap   =   NULL;  
PROCESSENTRY32   pe32   =   {NULL};  
CString   sCompare,   sTemp;  

       //sProcessFileName是你的進程名  
CString   sProcesFilename   =   m_pPath->ExtractFilename(sFilename);  
CLanguage   *   pLanguage   =   CLanguage::Instance();  

//調整統一大小寫格式,方便比較、  
#if   (_MFC_VER   <   0x0700)  
sProcesFilename.MakeLower();  
#else  
CString   sLowerTemp;  
sLowerTemp   =   sProcesFilename;  
sProcesFilename   =   sLowerTemp.MakeLower();  
#endif  

hProcessSnap   =   CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,   0);  

pe32.dwSize   =   sizeof(PROCESSENTRY32);  
//   系統進程快照  
if (Process32First(hProcessSnap,   &pe32))  
{  
do  
{  
sCompare.Format("%s",   pe32.szExeFile);  

#if   (_MFC_VER   <   0x0700)  
sCompare.MakeLower();  
#else  
CString   sLowerTemp;  
sLowerTemp   =   sCompare;  
sCompare   =   sLowerTemp.MakeLower();  
#endif  


//   Check   if   we   found   the   right   process  
if(sCompare   ==   sProcesFilename)  
{  
//   If   we   are   not   in   hidden   mode  
if(bAskUser)  
{  
//Set   up   confirmation   text  
sTemp.Format(pLanguage->GetString(IDS_CONFIRMATION_CLOSEAPPLICATION_EXPLANATION),  
sAppToClose,   sAppToUpdate,   sAppToClose);  

//Ask   confirmation  
CConfirmationDlg   dlgConfirm(pLanguage->GetString(IDS_CONFIRMATION_CLOSEAPPLICATION_TITLE),  
pLanguage->GetString(IDS_CONFIRMATION_TITLE),   sTemp,  
pLanguage->GetString(IDS_GENERAL_YES),   pLanguage->GetString(IDS_GENERAL_NO));  
if(dlgConfirm.DoModal()   ==   IDNO)  
{  
return   false;  
}  
}  

//   Get   handle   to   process  
HANDLE   hProcess   =   OpenProcess(PROCESS_ALL_ACCESS,   FALSE,   pe32.th32ProcessID);  

//   Exit   process  
DWORD   exCode;  
GetExitCodeProcess(hProcess,   &exCode);  
TerminateProcess(hProcess,   exCode);  

//   Wait   until   process   is   finished  
if   (WaitForSingleObject(hProcess,   30000)   ==   WAIT_TIMEOUT)  
return   false;  
}  
}   while   (Process32Next(hProcessSnap,   &pe32));  
}  
else  
{  
return   false;  
}  

return   true;  
}

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.
轉自:http://bbs.cfan.com.cn/viewthread.php?tid=793295
http://topic.csdn.net/t/20060424/09/4708145.html
http://student.csdn.net/space.php?uid=110004&do=thread&id=3278

posted on 2011-05-03 18:28 厚積薄發 閱讀(744) 評論(0)  編輯 收藏 引用 所屬分類: Windows編程

導航

<2025年11月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456

統計

常用鏈接

留言簿

隨筆分類

文章分類

文章檔案

搜索

最新評論

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲国产欧美在线人成| 一区二区三区欧美激情| 久久女同互慰一区二区三区| 中文精品视频一区二区在线观看| 国产精品jizz在线观看美国 | 国外精品视频| 欧美大秀在线观看| 黄色成人在线网址| 西瓜成人精品人成网站| 亚洲欧美日韩成人| 国产精品色婷婷久久58| 亚洲人成久久| 欧美日韩精选| 久久国产精品久久久| 亚洲黄色尤物视频| 国产精品久久久久一区| 欧美国产成人精品| 亚洲高清在线观看| 日韩一区二区免费看| 亚洲精选久久| 欧美精品一区二区三区很污很色的| 欧美成人精品一区二区三区| 国内伊人久久久久久网站视频| 亚洲精品三级| 国产精品久久国产三级国电话系列 | 国产日韩欧美一区| 欧美久久视频| 亚洲欧美成人一区二区在线电影| 国产午夜亚洲精品理论片色戒| 嫩草伊人久久精品少妇av杨幂| 国产精品久久久久影院色老大| 亚洲乱码精品一二三四区日韩在线 | 亚洲视频精选在线| 国产精品毛片va一区二区三区| 免费在线日韩av| 亚洲乱码精品一二三四区日韩在线 | 亚洲久久在线| 亚洲欧美视频一区| 亚洲国产黄色片| 欧美伊人久久| 欧美日韩黄色一区二区| 久久国产精品久久国产精品| 亚洲乱码国产乱码精品精天堂| 亚洲资源av| 欧美激情第五页| 久久久久久亚洲精品中文字幕| 男人的天堂亚洲| 国产日韩欧美二区| 国产精品网站在线观看| 久久久久久网址| 久久久777| 国产日韩欧美综合| 国产精品免费观看在线| 99视频有精品| 久久综合网络一区二区| 欧美日韩亚洲一区三区| 亚洲国产一区二区三区在线播 | 欧美在线观看视频在线| 欧美精品免费在线| 永久免费毛片在线播放不卡| 久久久久久久一区二区三区| 亚洲精品国产精品乱码不99按摩| 亚洲第一成人在线| 欧美激情第六页| 亚洲欧美日韩国产综合| 久久久精品动漫| 欧美日韩情趣电影| 久久精品国产精品亚洲| 欧美福利在线| 久久精品2019中文字幕| 久久精品亚洲国产奇米99| 亚洲美女视频网| 亚洲欧美日韩在线不卡| 在线成人h网| 亚洲国产高清aⅴ视频| 久久夜色精品国产欧美乱| 亚洲一区二区三区中文字幕 | 国产午夜精品福利| 欧美韩国日本综合| 国产视频一区三区| 亚洲精品国产精品乱码不99| 国产综合网站| 欧美综合国产| 欧美一区二区观看视频| 欧美午夜性色大片在线观看| 嫩草成人www欧美| 亚洲国产精品一区| 亚洲精品小视频在线观看| 亚洲国产精品综合| 欧美成人激情视频| 欧美激情第9页| 亚洲精品视频免费在线观看| 老司机成人在线视频| 美女图片一区二区| 91久久在线视频| 欧美日韩直播| 亚洲美女性视频| 亚洲一区二区三区激情| 国产视频精品va久久久久久| 久久xxxx| 欧美肥婆bbw| 国产精品99久久久久久宅男 | 欧美激情小视频| 亚洲国产精品专区久久| 国产精品久久久一本精品| 亚洲欧洲在线视频| 麻豆91精品| 日韩视频在线一区| 一本大道久久a久久精二百| 久久久久久久综合狠狠综合| 欧美福利在线观看| 蜜臀久久久99精品久久久久久 | 欧美高清一区二区| 亚洲精品视频在线| 麻豆精品传媒视频| 亚洲精品久久7777| 激情欧美日韩一区| 久久国产精品99国产精| 欧美中文字幕视频| 久久99在线观看| 久久女同互慰一区二区三区| 久久婷婷国产综合尤物精品| 性做久久久久久免费观看欧美| 亚洲日本va午夜在线电影 | 亚洲丶国产丶欧美一区二区三区 | 国内外成人免费激情在线视频网站| 黄色工厂这里只有精品| 欧美自拍偷拍| 亚洲国产日韩欧美| 欧美在线视频观看免费网站| 欧美日韩一区二区在线 | 国产欧美精品日韩| 亚洲国内自拍| 亚洲高清成人| 久久久久国产一区二区三区四区| 国产精品一二三视频| 午夜精品999| 亚洲黄网站黄| 麻豆精品精华液| 宅男噜噜噜66国产日韩在线观看| 午夜精品久久久久久久蜜桃app| 欧美精品一区二| 亚洲人成小说网站色在线| 久久久久久综合| 翔田千里一区二区| 国产精品亚洲一区| 亚洲综合电影一区二区三区| 亚洲一区免费在线观看| 在线观看精品视频| 欧美成人黑人xx视频免费观看| 久久久久久久性| 在线综合欧美| 久久久午夜视频| 国产亚洲精品高潮| 久久精品一区四区| 久久精品国产精品| 在线观看福利一区| 亚洲黄一区二区| 欧美日韩国产亚洲一区| 亚洲性感激情| 久久久久久久久久久一区| 激情亚洲网站| 欧美高清不卡| 欧美色综合天天久久综合精品| 亚洲影院在线| 久久经典综合| 一级日韩一区在线观看| 一区二区免费在线观看| 国产老女人精品毛片久久| 久久香蕉国产线看观看网| 欧美大香线蕉线伊人久久国产精品| 亚洲欧洲视频| 久久久精品国产免大香伊 | 亚洲欧洲日韩在线| 国产精品视频自拍| 欧美激情在线| 韩国精品在线观看| 亚洲欧美国产高清| 亚洲一区二区三区精品在线观看| 久久精品国产免费看久久精品| 亚洲一区二三| 免费精品视频| 欧美国产日韩亚洲一区| 国产老肥熟一区二区三区| 伊人春色精品| 亚洲欧美国产77777| 亚洲一区二区免费视频| 欧美日韩国产精品专区| 亚洲欧洲日夜超级视频| 99re这里只有精品6| 欧美国产第二页| 亚洲人成在线影院| 亚洲日本欧美| 欧美视频中文在线看| av成人黄色| 亚洲欧美日韩爽爽影院| 国产精品爽爽ⅴa在线观看| 亚洲视频欧美视频| 另类天堂视频在线观看| 在线观看日产精品|