2014-05-10 46 views
2

我試圖創建一個應用程序,只允許在所有Windows用戶的單個實例製作一個單獨的應用程序。所有用戶

我目前通過打開文件編寫和任由這樣做。這種方法是否安全?你知道使用C的另一種方法嗎?

回答

4

標準的解決方案是在應用程序啓動時創建一個全球性的mutex。應用程序第一次啓動時,這將成功。在隨後的嘗試中,它會失敗,並且這是您停止並無法加載第二個實例的線索。

通過調用CreateMutex function在Windows中創建互斥。正如鏈接文檔所指出的那樣,在Global\前面加上互斥體的名稱可確保它對所有終端服務器會話都可見,這正是您想要的。相比之下,前綴會使其僅在創建用戶會話的用戶會話中可見。

int WINAPI _tWinMain(...) 
{ 
    const TCHAR szMutexName[] = TEXT("Global\\UNIQUE_NAME_FOR_YOUR_APP"); 
    HANDLE hMutex = CreateMutex(NULL,  /* use default security attributes */ 
           TRUE,  /* create an owned mutex   */ 
           szMutexName /* name of the mutex    */); 
    if (GetLastError() == ERROR_ALREADY_EXISTS) 
    { 
     // The mutex already exists, meaning an instance of the app is already running, 
     // either in this user session or another session on the same machine. 
     // 
     // Here is where you show an instructive error message to the user, 
     // and then bow out gracefully. 
     MessageBox(hInstance, 
        TEXT("Another instance of this application is already running."), 
        TEXT("Fatal Error"), 
        MB_OK | MB_ICONERROR); 
     CloseHandle(hMutex); 
     return 1; 
    } 
    else 
    { 
     assert(hMutex != NULL); 

     // Otherwise, you're the first instance, so you're good to go. 
     // Continue loading the application here. 
    } 
} 

雖然有些人可能認爲這是可選的,因爲操作系統會爲您處理它,我一直主張明確清理好自己,調用ReleaseMutexCloseHandle當你的應用程序退出。這並不處理你崩潰並且沒有機會運行清理代碼的情況,但正如我所提到的,操作系統將在擁有進程終止後清除所有懸而未決的互斥體。

+0

http://blogs.msdn.com/b/oldnewthing/archive/2006/06/20/639479.aspx –

+0

我不記得有閱讀博客文章,但似乎相當明顯的給我。我不是單一實例應用程序的忠實粉絲,但如果你打算這樣做,我想不出一個更好的方法。雷蒙德關於不讓非管理員阻止其他用戶運行應用程序的建議很好,但我不完全確定如果您希望允許非管理員最初啓動應用程序,那麼您將如何實現這一點。我猜你必須編寫代碼才能在第二個實例由管理員啓動時將初始實例剔除。 –

+0

不要在這種情況下調用'ReleaseMutex()'。改用'CloseHandle()'。只有當你已經獲得了互斥鎖的所有權,你的代碼示例沒有做的時候(如果'CreateMutex()'報告了'ERROR_ALREADY_EXISTS',那麼'bInitialOwner'參數被忽略),才使用'ReleaseMutex()'。在這種情況下,應該將'bInitialOwner'參數設置爲FALSE而不是TRUE,因爲您不必擔心所有權,而只需要存在。 –