Подтвердить что ты не робот

Предотвращение нескольких экземпляров моего приложения

ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ

Снова я пишу по вышеуказанной проблеме (Предотвращение нескольких экземпляров моего приложения)

код работает, если я запускаю два экземпляра из меню программы/рабочего ярлыка. но в моем окружении,

один экземпляр запускается из Window Service.

другой из ярлыка рабочего стола с тем же параметром.

Любая помощь в написании кода?

4b9b3361

Ответ 1

Наиболее распространенным методом является использование мьютекса, аналогичного следующему:

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

Вы должны убедиться, что вы закрылись должным образом - сбой программы, который не удаляет мьютекс, может помешать запуску программы снова, хотя теоретически ОС будет очищать любые оборванные мьютексы после завершения процесса.

Другим широко используемым методом является поиск заголовков окон для названия программы:

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

Если значение null, то окно не найдено, поэтому программа не запущена. Вы можете использовать это, чтобы придать фокус запущенному приложению перед закрытием этого нового экземпляра, поэтому пользователю не остается удивляться, почему приложение не открылось.

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

Ответ 2

Вот простое решение, которое работает большую часть времени:

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

Другой способ:

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

И еще один способ:

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

Как и в другом упомянутом ответе, CreateMutex является наиболее распространенным, но он не идеален. Если вы хотите действительно тщательное решение и почему вышеуказанные способы не подходят, проверьте эту ссылку на Codeproject.

Ответ 3

TL;DR. Единственный безопасный и общий способ предотвращения нескольких экземпляров одного и того же процесса - использовать мьютекс, поскольку только это гарантировано, чтобы не дать вам условия гонки.

Здесь у вас хорошая статья о предмете. Я использовал его, когда мне нужно было что-то подобное, и решение работает отлично: Избегайте множественных событий.

Ответ 4

Вы ищете с именем mutex (с именем после аргумента, если это то, что должно запретить запуск приложения в нескольких экземплярах).

Ответ 5

Также я видел это решение без 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);
    }