Pregunta

Tengo una aplicación sin ventanas cuyo único propósito es instalar un archivo DLL de gancho de 32 bits y esperar hasta que el programa de los padres (un programa de 64 bits) salidas. El programa de 64 bits está escrito en C #, y la aplicación sin ventanas está escrito en C ++. Al principio tuve este bucle GetMessage que tenía el programa abierto:

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

I estaba cerrando la aplicación C ++ utilizando el método Process.Kill en C #, pero descubrí que que no permite la aplicación de C ++ a cerca limpiamente. Además, si la aplicación de C # se estrelló, la aplicación C ++ permanecería abierta para siempre. Hice la verificación de la aplicación de C ++ para ver si la aplicación de C # todavía está en marcha, el uso de este bucle:

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

    if(!isMainProgramRunning())
        break;

    Sleep(1000);
}

Por alguna razón el sueño causa problemas. Los ganchos instalados por el archivo DLL son WH_CBT y WH_KEYBOARD. Cada vez que pulse una tecla mientras la aplicación se está ejecutando C ++ con este bucle, las teclas sólo una comidos para arriba. Extracción del sueño hace que funcione bien, pero, como era de esperar, se utiliza el 100% de la CPU , que me no quieren. I intentado quitar el bucle de mensajes por completo y en su lugar utilizando WaitForSingleObject con un tiempo de espera infinito en un hilo que terminaría cuando isMainProgramRunning volvió falsa. Básicamente, esto encierra todo el equipo.

Yo realmente no entiendo por qué GetMessage, que, en lo que vi, nunca regresó, pero suspendió indefinidamente el hilo principal, no causaron estos problemas aún WaitForSingleObject hace que cada aplicación para congelar cuando hago clic en él. ¿Cómo puedo obtener la aplicación en C ++ para permanecer abierto hasta que se cierra la aplicación de C #?

Editar:

Desde que ha sido me señaló que dormir en una bomba de mensajes está mal, déjame preguntarte esto: ¿Hay una manera de especificar un tiempo de espera en el mensaje en espera, por lo que el programa no está esperando indefinidamente a un mensaje, pero más bien, va a esperar alrededor de 250 ms, tiempo de espera, me deja correr el método isMainProgramRunning, y luego esperar un poco más?

Edit2:

He intentado utilizar MsgWaitForMultipleObjects, aunque de una manera un tanto diferente al de Leo sugerido. Este es el bucle he utilizado:

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

    if(!isMainProgramRunning())
        break;
}

Una vez más he tenido el mismo problema con el sueño. También probé suspender el hilo principal y que tiene el otro hilo reanude. El mismo problema. Qué es lo que hace GetMessage que le permite esperar sin causar estos problemas? Tal vez esto debería ser el tema de otro post, pero ¿por qué es que cuando se suspende la aplicación C ++ instalación de los ganchos o duerme, todo el procesamiento de los ganchos para suspender parece así?

Edit3:

Este es el método DLL que las llamadas de aplicación C ++ para instalar los ganchos:

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);
}
¿Fue útil?

Solución

GetMessage nunca regresa es porque usted no tiene una ventana creada!

Para usar un mensaje en cola que hay que tener un poco de interfaz gráfica de usuario. Por ejemplo, puede crear una ventana oculta.

Otros consejos

Hay dos problemas distintos:

  1. ¿Cómo hacer que la salida del programa sin ventanas C ++ automáticamente si el programa sale de C # (por ejemplo bloqueos).

    En el programa de C ++, abra un identificador para el programa en C #. Dado que el programa de C # se ejecuta el programa en C ++, tener el programa en C # aprobar su propia PID como un argumento; el programa C ++ puede entonces abrir un identificador para ese proceso usando OpenProcess .

    A continuación, utilice MsgWaitForMultipleObjects en el bucle de mensajes. Si el programa de C # sale del mango que tiene a ella se indicará y se despertará. (También puede utilizar WaitForSingleObject(hProcess,0)==WAIT_OBJECT_0 para comprobar si el proceso se señaliza o no, por ejemplo, para verificar por qué despertaron, aunque los MsgWaitForMultipleObjects resultado le dirá que también.)

    Se debe cerrar el identificador de proceso a medida que está saliendo (aunque el sistema operativo lo hará por usted cuando se sale, es una buena práctica en caso de que vuelva a utilizar este código en un contexto diferente). Tenga en cuenta que el mango sobrevive al proceso que representa, y es por eso que se puede esperar en él.

  2. ¿Cómo hacer que el programa C # instruir al programa C ++ para la salida.

    Puede que no necesite para no recibir # 1 de trabajo, pero que sólo podría tener el programa en C # enviar un mensaje a la carpeta C ++ uno si lo desea.

    No utilice PostQuitMessage Y no publicar o enviar WM_QUIT través de hilos o procesos.

    En su lugar, enviar algún otro mensaje que las dos aplicaciones están de acuerdo en (por ejemplo WM_APP + 1) usando PostThreadMessage .

Se puede crear un evento con nombre y uso:

MsgWaitForMultipleObjects

en su bucle de mensajes.

La aplicación de C # es suficiente con abrir y levantar este evento para informar a su aplicación a la salida.

Es una especie de comunicación mínima entre procesos.

Se debe salir del proceso mediante la publicación de un mensaje a WM_QUIT y la manipulación correcta, como se especifica en este artículo (Modalidad) , por Raymond Chen. No dormir dentro de un bucle sin manipular mensajes - que está mal. Su aplicación debe ser ya sea manejando un mensaje o en espera de nuevos mensajes.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top