2010-11-16 12 views
10

Mam aplikację, która używa połączenia przez gniazdo do wysyłania i odbierania danych z innej aplikacji. Podczas tworzenia gniazda używa portu 4998.Jak uruchomić tylko jedną instancję aplikacji

Na tym polega mój problem. Po uruchomieniu aplikacji gniazdo zaczyna korzystać z portu 4998. Jeśli chcę ponownie uruchomić aplikację, otrzymam błąd powiązania z gniazdem.

Dlatego chcę ograniczyć instancję aplikacji do jednego. Oznacza to, że jeśli aplikacja jest już uruchomiona i ktoś próbuje uruchomić aplikację ponownie, klikając ikonę exe lub skrót, nie powinien uruchamiać programu, zamiast tego powinien przenieść istniejącą aplikację na górę.

Odpowiedz

10

Możesz użyć nazwanego muteksa.

przykładowy kod z article:

WINAPI WinMain(
    HINSTANCE, HINSTANCE, LPSTR, int) 
{ 
    try { 
    // Try to open the mutex. 
    HANDLE hMutex = OpenMutex(
     MUTEX_ALL_ACCESS, 0, "MyApp1.0"); 

    if (!hMutex) 
     // Mutex doesn’t exist. This is 
     // the first instance so create 
     // the mutex. 
     hMutex = 
     CreateMutex(0, 0, "MyApp1.0"); 
    else 
     // The mutex exists so this is the 
     // the second instance so return. 
     return 0; 

    Application->Initialize(); 
    Application->CreateForm(
     __classid(TForm1), &Form1); 
    Application->Run(); 

    // The app is closing so release 
    // the mutex. 
    ReleaseMutex(hMutex); 
    } 
    catch (Exception &exception) { 
    Application-> 
     ShowException(&exception); 
    } 
    return 0; 
} 
+12

Najpierw wywołując OpenMutex(), masz stan wyścigu. Najpierw wywołaj CreateMutex/Ex(). Powie Ci, czy muteks już istnieje. Wywołaj OpenMutex() tylko wtedy, gdy CreateMutex() zawiedzie z błędem ERROR_ACCESS_DENIED. –

+0

Jakieś wskazówki, jak zrobić to na Win7 +? Globalne \ x muteksy nie widzą się z różnych sesji logowania użytkownika ... –

+1

@ RomanPlášil tak naprawdę to zrobiliście, musieliście zrobić coś złego – paulm

3

Utwórz nazwane wydarzenie na początku i sprawdź wynik. Zamknij aplikację, jeśli wydarzenie już istnieje.

BOOL CheckOneInstance() 
{ 
    m_hStartEvent = CreateEventW(NULL, TRUE, FALSE, L"EVENT_NAME_HERE"); 
    if (GetLastError() == ERROR_ALREADY_EXISTS) { 
     CloseHandle(m_hStartEvent); 
     m_hStartEvent = NULL; 
     // already exist 
     // send message from here to existing copy of the application 
     return FALSE; 
    } 
    // the only instance, start in a usual way 
    return TRUE; 
} 

Zamknij m_hStartEvent przy wyjściu z aplikacji.

+0

Jeśli CreatEvent() nie powiedzie się, nie można stwierdzić, czy aplikacja już działa, więc należy wyjść, a nie kontynuować. –

1

Nie masz już sposób, aby sprawdzić, czy aplikacja jest uruchomiona? Kto potrzebuje Mutexa, jeśli port jest już zajęty, wiesz, że aplikacja działa!

+0

Tak Teraz zamiast pokazywać błąd, muszę podać swoją aplikację za pomocą procesu ID. Jakaś pomoc? – Simsons

+5

Tylko dlatego, że port jest używany, nie oznacza to, że TWOJA aplikacja go używa. –

+0

@ OJ, Good Catch. Port może być używany przez inną, trudniejszą aplikację. – Simsons

4

/* Znalazłem niezbędną edycję do zrobienia. Dodano kilka dodatkowych kodów i zmian, które są potrzebne. Obecny działa doskonale dla mnie. Dziękuję, Kirill V. Lyadvinsky i Remy Lebeau za pomoc !!

*/

bool CheckOneInstance() 
{ 

    HANDLE m_hStartEvent = CreateEventW(NULL, FALSE, FALSE, L"Global\\CSAPP"); 

    if(m_hStartEvent == NULL) 
    { 
    CloseHandle(m_hStartEvent); 
     return false; 
    } 


    if (GetLastError() == ERROR_ALREADY_EXISTS) { 

     CloseHandle(m_hStartEvent); 
     m_hStartEvent = NULL; 
     // already exist 
     // send message from here to existing copy of the application 
     return false; 
    } 
    // the only instance, start in a usual way 
    return true; 
} 

/* Powyższy kod działa nawet wtedy, gdy ktoś próbuje otworzyć drugą instancję z innej LOGIN opuszczeniu pierwszego główna Otwórz z jego instancji działającej. */

2

Po uruchomieniu aplikacji utwórz muteks. Jeśli już istnieje, znajdź istniejącą aplikację i przenieś ją na pierwszy plan. Jeśli aplikacja ma ustalony tytuł dla swojego głównego okna, łatwo ją znaleźć pod numerem FindWindow.

m_singleInstanceMutex = CreateMutex(NULL, TRUE, L"Some unique string for your app"); 
if (m_singleInstanceMutex == NULL || GetLastError() == ERROR_ALREADY_EXISTS) { 
    HWND existingApp = FindWindow(0, L"Your app's window title"); 
    if (existingApp) SetForegroundWindow(existingApp); 
    return FALSE; // Exit the app. For MFC, return false from InitInstance. 
} 
Powiązane problemy