2010-11-16 7 views
10

У меня есть приложение, которое использует соединение сокета для отправки и получения данных из другого приложения. При создании сокета он использует порт 4998.Как запустить только один экземпляр приложения

Вот где моя проблема. Как только я запустил приложение, сокет начнет использовать порт 4998. Поэтому, если я хочу снова выполнить приложение, я получаю ошибку привязки сокета.

Поэтому я хочу ограничить свой экземпляр приложения одним. Это означает, что если приложение уже запущено, а кто-то пытается запустить приложение снова, нажав значок exe или ярлык, он не должен запускать программу, вместо этого он должен привести существующее приложение в верхнюю часть.

ответ

10

Вы можете использовать named mutex.

Пример кода из 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

Сначала вызывается OpenMutex(), у вас есть условие гонки. Сначала вызовите CreateMutex/Ex(). Он расскажет вам, существует ли мьютекс. Вызовите OpenMutex() только в случае сбоя CreateMutex() с ошибкой ERROR_ACCESS_DENIED. –

+0

Любые советы о том, как сделать эту работу на Win7 +? Глобальные \ x мьютексы не видят друг друга из разных сеансов входа в систему ... –

+1

@ RomanPlášil они действительно делают, вы, должно быть, сделали что-то не так – paulm

3

Создайте именованное событие в начале и проверьте результат. Закройте приложение, если событие уже существует.

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; 
} 

Закрыть m_hStartEvent на выходе приложения.

+0

Если функция CreatEvent() не удалась, вы не можете определить, запущено ли приложение или нет, поэтому вы должны выйти, а не продолжить. –

1

Не у вас уже есть способ проверить, если ваше приложение работает? Кому нужен Mutex, если порт уже сделан, вы знаете, что приложение запущено!

+0

Да Теперь я вместо того, чтобы показывать ошибку, мне нужно принести мое приложение, используя процесс Я БЫ. Любая помощь? – Simsons

+5

Просто потому, что порт используется, это не означает, что ваше приложение использует его. –

+0

@ OJ, Good Catch. Порт может использоваться приложением – Simsons

4

/* Я нашел необходимое редактирование. Добавлен дополнительный код и исправления, которые необходимы. Настоящий отлично работает для меня. Спасибо, Кирилл В. Лядвинский и Реми Лебо за помощь!

*/

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; 
} 

/* Приведенный выше код работает даже тогда, когда один пытается открыть второй экземпляр ИЗ РАЗЛИЧНЫХ ВХОД покидающий первый ВХОД ОТКРЫТ с ITS INSTANCE RUNNING. */

2

Когда ваше приложение инициализируется, создайте мьютекс. Если он уже существует, найдите существующее приложение и выведите его на передний план. Если приложение имеет фиксированное название для своего главного окна, его можно легко найти с помощью 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. 
} 
Смежные вопросы