Работает только двойной экземпляр - PullRequest
0 голосов
/ 12 апреля 2020

Я прошу помощи. Мне нужно иметь возможность запускать только 2 экземпляра моего приложения, но с помощью приведенного ниже кода можно запустить более 2 экземпляров. Я не уверен, что мне не хватает.

Вот код:

const char szUniqueNamedSemaphore[] = "Amazon.exe";
HANDLE hHandle = CreateSemaphore(NULL, 2, 2, szUniqueNamedSemaphore);
if (!hHandle)
{
    MessageBox(NULL, "Unexpected error creating Execution!", "Amazon.exe", MB_OK);
    return FALSE;
}
if (WaitForSingleObject(hHandle, 0) != WAIT_OBJECT_0)
{
    MessageBox(NULL, "Game is already running 2 times, additional Execution is prohibited!", "Amazon.exe", MB_OK);
    return FALSE;
}
ReleaseSemaphore(hHandle, 1, NULL);

Ответы [ 2 ]

2 голосов
/ 12 апреля 2020

Проблема в том, что вы освобождаете семафор, увеличивая его счетчик, сразу после того, как вы успешно дождетесь его, что уменьшает его счетчик. Таким образом, его счетчик всегда равен 2 в начале каждого нового экземпляра. Не выпускайте семафор до тех пор, пока вы не будете готовы выйти из программы после ее работы, например:

const char* szUniqueNamedSemaphore = "Amazon.exe";

int main() // or WinMain()...
{
    HANDLE hHandle = CreateSemaphore(NULL, 2, 2, szUniqueNamedSemaphore);
    if (!hHandle)
    {
        MessageBox(NULL, "Unexpected error creating Execution!", "Amazon.exe", MB_OK);
        return 0;
    }

    DWORD ret = WaitForSingleObject(hHandle, 0);
    if (ret != WAIT_OBJECT_0)
    {
        if (ret == WAIT_TIMEOUT)
            MessageBox(NULL, "Game is already running 2 times, additional Execution is prohibited!", "Amazon.exe", MB_OK);
        else
            MessageBox(NULL, "Unexpected error waiting on Execution!", "Amazon.exe", MB_OK);
        return 0;
    }

    // do your normal work...

    ReleaseSemaphore(hHandle, 1, NULL);
    return 0;
}
0 голосов
/ 12 апреля 2020

То, как семафоры windows работают, блокирует ваш третий экземпляр, WaitForSingleObject для семафора завершается, когда доступное число равно не ноль, а не наоборот. Не существует межпроцессного примитива, который будет делать то, что вам нужно.

Я предлагаю объединить мьютекс и раздел с общей памятью (это раздел памяти, общий для всех экземпляров вашей программы) и сохранить количество запущенных экземпляров в этом разделе. MSV C допускает синтаксис, подобный следующему:

#pragma section("myShared", read,write,shared)
__declspec(allocate("myShared")) ULONG g_uInstances = 0;

Вы можете использовать InterlockedIncrement / InterlockedDecrement вместо мьютекса, но вам нужно помнить, чтобы уменьшить счетчик даже в том случае, если вы превысили предел.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...