2012-01-10 30 views
12

THÔNG TIN BỔ SUNGNgăn chặn nhiều trường hợp của ứng dụng của tôi

Một lần nữa tôi đang viết về vấn đề trên (Ngăn chặn nhiều trường hợp của ứng dụng của tôi)

mã làm việc cho nếu tôi bắt đầu hai trường hợp từ menu programe/shortcut trên desktop . nhưng trong môi trường của tôi,

một phiên bản đang chạy từ Dịch vụ cửa sổ.

một từ lối tắt trên Màn hình với thông số Tương tự.

Bất kỳ trợ giúp nào về cách viết mã?

+0

Tại sao không nên nó được cho phép? Tôi hỏi vì nếu chương trình là một cái gì đó giống như một máy chủ lắng nghe trên một số cổng cố định, bạn không thực sự phải làm bất cứ điều gì đặc biệt. – hvd

+0

@hvd, có nhiều loại chương trình, không nên cho phép thực hiện nhiều phiên bản. Nếu không, sẽ không có mutexes trong thư viện hệ thống. – Griwes

+0

Có ứng dụng đó là một máy chủ, nhưng nó có thể chạy cho nhiều trường hợp nhưng không phải với cùng một đối số. nếu chúng ta vượt qua cùng một đối số từ dịch vụ cửa sổ và bắt đầu ABC.exe và từ phím tắt Desktop với cùng một đối số ABC.exe thứ hai không nên bắt đầu. –

Trả lời

3

Bạn đang tìm kiếm named mutex (được đặt tên sau đối số, nếu đó là những gì không cho phép ứng dụng chạy trong nhiều phiên bản).

7

Đây là một giải pháp đơn giản mà làm việc hầu hết thời gian:

CreateEvent(NULL, FALSE, FALSE, "MyEvent"); 
if (GetLastError() == ERROR_ALREADY_EXISTS) 
{ 
    // Do Stuff 
    return FALSE; 
} 

Một cách khác:

CreateSemaphore(NULL, TRUE, TRUE, "MySemaphore"); 
if (GetLastError() == ERROR_ALREADY_EXISTS) 
{ 
    // Do Stuff 
    return FALSE; 
} 

Và một cách khác:

CreateMutex(NULL, TRUE, "MyMutex"); 
if (GetLastError() == ERROR_ALREADY_EXISTS) 
{ 
    // Do Stuff 
    return FALSE; 
} 

As, câu trả lời khác được đề cập , CreateMutex là phổ biến nhất nhưng nó không phải là hoàn hảo. Nếu bạn muốn một giải pháp thực sự toàn diện và tại sao những cách trên không tốt, hãy kiểm tra điều này link on Codeproject.

+0

Lưu ý rằng các đối tượng này không thể sử dụng cùng một chuỗi (đối với lpName) nếu bạn sử dụng chúng cùng nhau, nếu không chúng sẽ đưa ra một lỗi khác. – Andrew

10

Phương pháp phổ biến nhất là sử dụng một mutex, tương tự như sau:

int WINAPI WinMain(...) 
{ 
    const char szUniqueNamedMutex[] = "com_mycompany_apps_appname"; 
    HANDLE hHandle = CreateMutex(NULL, TRUE, szUniqueNamedMutex); 
    if(ERROR_ALREADY_EXISTS == GetLastError()) 
    { 
     // Program already running somewhere 
     return(1); // Exit program 
    } 

    // Program runs... 

    // Upon app closing: 
    ReleaseMutex(hHandle); // Explicitly release mutex 
    CloseHandle(hHandle); // close handle before terminating 
    return(1); 
} 

Bạn phải chắc chắn rằng bạn đóng đúng cách - một vụ tai nạn chương trình mà không loại bỏ các mutex có thể có thể ngăn chặn sự chương trình từ chạy một lần nữa, mặc dù trong lý thuyết hệ điều hành sẽ làm sạch bất kỳ mutexes lơ lửng khi quá trình kết thúc.

Một phương pháp thường được sử dụng là để tìm kiếm tiêu đề cửa sổ cho danh hiệu chương trình:

HWND hWnd=::FindWindow(LPCTSTR lpClassName, // pointer to class name 
         LPCTSTR lpWindowName // pointer to window name 
         ); 

Nếu đó là null, sau đó cửa sổ không được tìm thấy, do đó chương trình không chạy. Bạn có thể sử dụng tính năng này để tập trung vào ứng dụng đang chạy trước khi đóng phiên bản mới này, vì vậy người dùng không được tự hỏi tại sao ứng dụng không mở.

if(hWnd != NULL) 
{ 
    ShowWindow(hWnd,SW_NORMAL); 
    // exit this instance 
    return(1); 
} 
+0

Bạn không quên 'ReleaseMutex'? –

+0

@Jesse Nó được phát hành khi bạn CloseHandle nó, nhưng nếu bạn quan tâm đến được rõ ràng, một cuộc gọi đến ReleaseMutex sẽ là tốt. http://msdn.microsoft.com/en-us/library/windows/desktop/ms724211%28v=vs.85%29.aspx –

+0

Tôi không nghĩ đó là sự thật. Tôi nghĩ bạn phải gọi 'ReleaseMutex'. Kiểm tra [SO câu hỏi] này (http://stackoverflow.com/questions/5034339/closehandle-on-a-mutex-before-releasemutex-what-happens) và cũng đọc các nhận xét cho [CreateMutex] (http: // msdn.microsoft.com/en-us/library/aa914601.aspx). Tuy nhiên, tôi nhận ra nó có lẽ không quan trọng trong trường hợp này mặc dù. –

5

TLDR: Cách duy nhất an toàn và chung để ngăn chặn nhiều trường hợp của quá trình tương tự là sử dụng một mutex, vì chỉ này được guaranted để không cung cấp cho bạn một điều kiện chủng tộc.

Ở đây bạn có một bài viết hay về chủ đề này. Tôi đã sử dụng nó khi phải làm điều gì đó tương tự và giải pháp hoạt động hoàn hảo: AvoidingMultipleInstances.

1

Ngoài ra tôi đã nhìn thấy giải pháp này, mà không GetLastError():

HANDLE hMutex = CreateMutexA(NULL, FALSE, "my mutex"); 
    DWORD dwMutexWaitResult = WaitForSingleObject(hMutex, 0); 
    if (dwMutexWaitResult != WAIT_OBJECT_0) 
    { 
     MessageBox(HWND_DESKTOP, TEXT("This application is already running"), TEXT("Information"), MB_OK | MB_ICONINFORMATION); 
     CloseHandle(hMutex); 
    } 
Các vấn đề liên quan