Frage

Ich habe eine fensterlose Anwendung, deren einziger Zweck es ist eine 32-Bit-Hook-DLL-Datei zu installieren und bis das übergeordnete Programm warten (ein 64-Bit-Programm) beendet. Das 64-Bit-Programm ist geschrieben in C # und die fensterlos Anwendung ist in C ++ geschrieben. Ich hatte ursprünglich diese GetMessage Schleife, die das Programm offen gehalten:

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

Ich war Schließen der C ++ Anwendung der Process.Kill Methode in C #, aber ich fand heraus, dass das nicht ist, so dass die C ++ Anwendung zu schließen sauber. Auch wenn die C # Anwendung abgestürzt ist, die C ++ Anwendung würde offen bleiben für immer. Ich habe die C ++ Anwendung überprüfen, ob die C # Anwendung noch ausgeführt wird, mit dieser Schleife:

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

    if(!isMainProgramRunning())
        break;

    Sleep(1000);
}

Aus irgendeinem Grunde bewirkt, dass die Schlafprobleme. Die Haken von der DLL-Datei installiert sind WH_CBT und WH_KEYBOARD. Jedes Mal, wenn ich eine Taste drücken, während der C ++ Anwendung mit dieser Schleife ausgeführt wird, die Tasten nur bis gefressen. Das Entfernen der Schlaf macht es gut funktionieren, aber, wie erwartet, verwendet es 100% CPU , die ich nicht wollen. Ich versuchte Entfernen der Nachrichtenschleife insgesamt und stattdessen unter Verwendung von WaitForSingleObject mit einer unendlichen Zeitüberschreitung auf einem Faden, enden würde, wenn isMainProgramRunning falsch zurückgegeben. Dies verriegelt im Grunde den ganzen Computer.

Ich verstehe wirklich nicht, warum GetMessage, die, soweit ich sehe, kommt nie wieder, aber das Hauptthread unbestimmter Zeit ausgesetzt, nicht die Ursache für diese Probleme noch WaitForSingleObject jede Anwendung verursacht einfrieren, wenn ich darauf klicken. Wie kann ich die C ++ erhalten Anwendung geöffnet bleiben, bis die C # Anwendung schließt?

Edit:

Da es wurde mir darauf hingewiesen, dass ist schlecht in einer Meldungsverteilschleife schlafen, lassen Sie mich fragen: Gibt es eine Möglichkeit, einen Timeout auf die Nachricht warten zu geben, so dass das Programm nicht auf unbestimmte Zeit auf eine Nachricht warten, aber vielmehr etwa 250 ms, Timeout warten, lassen Sie mich das isMainProgramRunning Verfahren laufen, dann etwas mehr warten?

Edit2:

Ich habe versucht MsgWaitForMultipleObjects mit, wenn auch in etwas anderer Weise als Leo vorgeschlagen. Dies ist die Schleife I verwendet:

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

    if(!isMainProgramRunning())
        break;
}

Auch ich hatte das gleiche Problem mit dem Schlaf. Ich habe auch den Haupt-Thread Suspendieren und mit dem anderen Thread es wieder aufzunehmen. Gleiches Problem. Was ist es, dass GetMessage ist, dass es, ohne dass diese Probleme warten lässt? Vielleicht soll dies das Thema eines anderen Posts, aber warum ist, dass es, wenn die C ++ Anwendung des Haken sleeps Installation oder suspendiert ist, die gesamte Verarbeitung in dem Haken scheint auch zu suspendieren?

Edit3:

Hier ist die DLL-Methode, dass die C ++ Anwendung ruft den Haken zu installieren:

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);
}
War es hilfreich?

Lösung

GetMessage nie zurückgibt, ist, weil Sie nicht ein Fenster erstellt haben!

Um eine Nachricht-Warteschlange verwenden Sie haben einige GUI haben. Sie können zum Beispiel ein ausgeblendetes Fenster erstellen.

Andere Tipps

Sie haben zwei verschiedene Probleme:

  1. Wie die fensterlos C ++ Programmende automatisch zu machen, wenn das C # Programm beendet (z stürzt ab).

    In der C ++ Programm, öffnen Sie ein Handle auf das C # -Programm. Da das C # Programm des C ++ Programm ausgeführt wird, hat das C # Programm seine eigene PID als Argument übergeben; das C ++ Programm kann dann öffnen ein Handle auf diesen Prozess mit Open .

    Dann nutzen Sie MsgWaitForMultipleObjects Ihre Nachrichtenschleife. Wenn das C # Programm beendet die Greifen Sie es haben wird signalisiert und Sie werden aufwachen. (Sie können auch WaitForSingleObject(hProcess,0)==WAIT_OBJECT_0 verwenden um zu überprüfen, ob der Prozess signalisiert wird oder nicht, zum Beispiel, um zu überprüfen, warum Sie aufgeweckt wurden, obwohl die MsgWaitForMultipleObjects wird zeigen, führen Sie das auch.)

    Sie sollten den Prozess-Handle schließen, wie Sie Beenden (obwohl das Betriebssystem es für Sie tun, wenn Sie verlassen, es ist eine gute Übung für den Fall, Sie wiederverwenden, diesen Code in einem anderen Kontext). Beachten Sie, dass der Griff den Prozess überlebt es darstellt, und das ist, warum Sie auf sie warten.

  2. Wie das C # Programm anweisen, das C ++ Programm zu beenden machen.

    Sie müssen dies nicht, wenn Sie # 1 zum Laufen zu bringen, aber man könnte nur das C # Programm eine Nachricht an den C ++ ein, wenn Sie möchten.

    Verwenden Sie PostQuitMessage nicht maßstäblich und keine Post oder WM_QUIT über Threads oder Prozesse senden.

    Stattdessen schreibt eine andere Nachricht, dass die beiden Apps stimmen auf (zB WM_APP + 1) mit Postthreadmessage .

Sie können ein benanntes Ereignis erstellen und verwenden:

MsgWaitForMultipleObjects

in Ihrer Nachrichtenschleife.

Die C # Anwendung müssen nur öffnen und dieses Ereignis heben Sie Ihre Anwendung zu beenden erzählen.

Es ist eine Art von minimal übergreifende Kommunikation.

Sie sollten den Prozess beenden, indem eine WM_QUIT Nachricht, um es zu veröffentlichen und es eine korrekte Abwicklung, wie in dieser Artikel (Modality) , von Raymond Chen. Schlafen Sie nicht in einer Schleife ohne Nachrichten Handhabung - es ist falsch. Ihre Anwendung sollte entweder eine Nachricht seinen Umgang mit oder wartet auf neue Nachrichten.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top