Вопрос

У меня есть приложение без окон, единственная цель, установленная 32-битная файл DLL и ждать, пока исходная программа (64-битная программа) выходит. 64-битная программа написана в C#, а приложение без окон написано в C ++. Первоначально у меня был этот цикл GetMessage, который удерживал программу открытой:

while(GetMessage(&msg, NULL, 0, 0) > 0)
{
    TranslateMessage(&msg);
    DispatchMessage(&msg);
}

Я закрывал приложение C ++, используя метод Process.kill в C#, но я обнаружил, что это не позволяет приложению C ++ чистого закрытия. Кроме того, если приложение C# сбоялось, приложение C ++ останется открытым навсегда. Я сделал проверку приложения C ++, чтобы увидеть, работает ли приложение C#, используя этот цикл:

while(true)
{
    if(PeekMessage(&msg, NULL, 0, 0, true))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    if(!isMainProgramRunning())
        break;

    Sleep(1000);
}

По какой -то причине сон вызывает проблемы. Крюки, установленные файлом DLL, являются WH_CBT и WH_KEYBOARD. Всякий раз, когда я нажимаю клавишу, пока приложение C ++ работает с этим циклом, клавиши просто съедены. Удаление сна заставляет его работать нормально, но, как и ожидалось, он использует 100% Процессор, чего я не хочу. Я попытался снять петлю сообщения вообще и вместо этого с использованием waitForsingleObject с бесконечным тайм -аутом на потоке, который закончится, когда IsmainProgramrunning вернул False. Это в основном блокирует весь компьютер.

Я не совсем понимаю, почему GetMessage, который, насколько я видел, никогда не вернулся, но приостановил основную нить на неопределенный срок, не вызывал этих проблем, но WaitForsingleObject приводит к замораживанию каждого приложения, когда я нажимаю на нее. Как я могу заставить приложение C ++ оставаться открытым, пока приложение C# не закроется?

Редактировать:

Поскольку мне было отмечено, что сон в насосе сообщения плохой, позвольте мне спросить это: есть ли способ указать тайм -аут в ожидании сообщения, поэтому программа не ждет на неопределенное время для сообщения, но скорее будет Подождите около 250 мс, тайм -аут, позвольте мне запустить метод IsmainProgromrunning, а затем подождать еще?

Edit2:

Я попытался использовать msgwaitformultipleobjects, хотя и отличающимся, чем предложил Лео. Это петля, которую я использовал:

while(MsgWaitForMultipleObjects (0, NULL, true, 250, QS_ALLPOSTMESSAGE) != WAIT_FAILED)
{
    if(PeekMessage(&msg, NULL, 0, 0, true))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    if(!isMainProgramRunning())
        break;
}

У меня снова была та же проблема со сном. Я также попытался приостановить основную ветку и иметь другую нить возобновить его. Та же проблема. Что делает GetMessage, который позволяет ему ждать, не вызывая этих проблем? Может быть, это должен быть предметом другого поста, но почему, когда приложение C ++, устанавливающее крючки, спит или приостановлено, вся обработка в крючках, кажется, также приостанавливается?

РЕДАКТИРОВАТЬ3:

Вот метод DLL, который вызовы приложения C ++ для установки крючков:

extern "C" __declspec(dllexport) void install()
{
    cbtHook = SetWindowsHookEx(WH_CBT, hookWindowEvents, hinst, NULL);

    if(cbtHook == NULL)
        MessageBox(NULL, "Unable to install CBT hook", "Error!", MB_OK);

    keyHook = SetWindowsHookEx(WH_KEYBOARD, LowLevelKeyboardProc, hinst, NULL);

    if(keyHook == NULL)
        MessageBox(NULL, "Unable to install key hook", "Error!", MB_OK);
}
Это было полезно?

Решение

GetMessage никогда не возвращается, потому что у вас нет созданного окна!

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

Другие советы

У вас есть две отдельные проблемы:

  1. Как сделать программу без окон C ++ автоматически, если программа C# выходит (например, сбои).

    В программе C ++ откройте ручку для программы C#. Поскольку программа C# запускает программу C ++, попросите программу C# передать свой собственный PID в качестве аргумента; Программа C ++ может затем открыть ручку для этого процесса, используя OpenProcess.

    Затем используйте Msgwaitformultipleobjects В вашем цикле сообщения. Если программа C# выйдет из ручки, который вам придется, будет сигнализируется, и вы проснетесь. (Вы также можете использовать WaitForSingleObject(hProcess,0)==WAIT_OBJECT_0 Чтобы проверить, сигнализируется ли процесс или нет, например, чтобы проверить, почему вас разбудили, хотя результат msgwaitformultipleobjects также сообщит вам об этом.)

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

  2. Как заставить программу C# инструктировать программу C ++ выйти.

    Возможно, вам это не понадобится, если вы получите № 1, но вы можете просто попросить программу C # публиковать сообщение C ++ One, если хотите.

    Не используйте PostQuitMessage и не публикуйте и не отправляйте wm_quit через потоки или процессы.

    Вместо этого опубликуйте какое -то другое сообщение, с которым два приложения согласуются (например, WM_APP+1), используя PostThreadMessage.

Вы можете создать именованное событие и использовать:

Msgwaitformultipleobjects

В вашем цикле сообщения.

Приложение C# должно открыть и поднять это событие, чтобы сообщить вашему приложению для выхода.

Это своего рода минимальное межпроцессное общение.

Вы должны выйти из процесса, разместив к нему сообщение WM_QUIT и правильно обработали его, как указано в Эта статья (Модальность), Рэймонд Чен. Не спите в петле, не обрабатывая сообщения - это неправильно. Ваше приложение должно либо обрабатывать сообщение, либо ожидание новых сообщений.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top