Cómo utilizar Conjunto ConsoleHandler () para bloquear las llamadas de salida

StackOverflow https://stackoverflow.com/questions/533491

  •  22-08-2019
  •  | 
  •  

Pregunta

Yo sé que tengo que usar setconsolehandler() si quiero gestionar eventos de cierre de la consola.

No sé cómo bloquear la CTRL_CLOSE_EVENT. He intentado volver verdadero / falso si las capturas ese evento, pero sin éxito

Esto es lo que tengo hasta ahora (gracias Anton Gogolev!)

[DllImport("Kernel32")]
public static extern bool SetConsoleCtrlHandler(HandlerRoutine Handler, bool Add);

public delegate bool HandlerRoutine(CtrlTypes CtrlType);

public enum CtrlTypes{
    CTRL_C_EVENT = 0,
    CTRL_BREAK_EVENT,
    CTRL_CLOSE_EVENT,
    CTRL_LOGOFF_EVENT = 5,
    CTRL_SHUTDOWN_EVENT
}

private static bool ConsoleCtrlCheck(CtrlTypes ctrlType)
{ 
    if(ctrlType == CtrlTypes.CTRL_CLOSE_EVENT)
        return false;// I have tried true and false and viceversa with the return   
                     // true/false but I cant seem to get it right.
    return true;
}


//and then I use this to call it
SetConsoleCtrlHandler(new HandlerRoutine(ConsoleCtrlCheck), true);

También es posible ejecutar un nuevo hilo para controlar si la consola está cerrando y el bloque que se cierran si el hilo principal está en el medio de hacer algo?

¿Fue útil?

Solución

La documentación de SetConsoleCtrlHandler() dice:

  

El sistema genera CTRL_CLOSE_EVENT, CTRL_LOGOFF_EVENT, y las señales CTRL_SHUTDOWN_EVENT cuando el usuario cierra la consola, cierra la sesión o se apaga el sistema para que el proceso tenga la oportunidad de limpiar antes de la terminación.

Esto implica que a diferencia de la manipulación de fenómenos de rotura CTRL + C o CTRL +, el proceso no tienen la oportunidad de cancelar el cierre, cierre de sesión o apagado.

Otros consejos

En realidad se puede bloquearlo (He reproducido esto en Windows XP por lo menos). Por ejemplo, si en el controlador tiene una interminable bucle while con un sueño, esto va a parar este proceso de terminación para siempre (o por lo menos por un largo tiempo, o hasta que el usuario mata al proceso a través del administrador de tareas).

Si realmente se necesita para iniciar un hilo, se puede usar una condición de espera (AutoResetEvent en C #) y comenzar su hilo (aunque un nuevo hilo probablemente no se necesita en la mayoría de los casos) y luego notificar a la condición de espera cuando el hilo es terminado. Sin embargo, sólo haciendo cualquier limpieza en el controlador sería suficiente en la mayoría de los casos.

Si en el peor caso de que no espere para siempre, el proceso se mantendrán en funcionamiento y usted será capaz de ver que cuando se vuelva a conectar (por lo menos en Windows XP). Sin embargo, esto hace que el escritorio para hacer una pausa durante 20 segundos antes de ir a la pantalla de la sesión (mientras espera a que su applicaiton para salir), y luego se detiene de nuevo en la viga de pantalla (supongo mientras intenta para un segundo tiempo) . Por supuesto, yo recomiendo no esperar por siempre; para cualquier material duradero que realmente debería poner esto en un servicio.

He encontrado una posible 'piratear' que podrían evitar que la aplicación de cierre, mientras que todavía perfectamente la obediencia a la solicitud de cierre de la consola. En particular, este es adecuado, creo, para aplicaciones de interfaz gráfica de usuario que han creado una consola como un 'extra'. A partir de la documentación de MSDN, en el punto donde el Ctrl Handler se llama nuevo hilo se crea en el proceso para llamar al manejador. Mi solución, entonces, es matar el hilo agredir invasor antes de que el controlador predeterminado puede llamar ExitProcess. En la rutina de controlador (código en C ++):

// Detach Console:
FreeConsole();
// Prevent closing:
ExitThread(0);
return TRUE; // Not reached

EDIT: Parece esto causa algunos problemas, como es de esperar, supongo. Las siguientes llamadas a AllocConsole () se bloquea indefinidamente, por lo que sospecho que sale de la rosca antes de tiempo no limpiar adecuadamente.

EDIT 2:

Para aclarar más arriba, he encontrado ningún problema directos con la continuación para ejecutar el programa. Pero hay que tener en cuenta que hemos terminado con fuerza un hilo que KERNEL32 ha creado, por lo que cualquier recurso dentro kernel32 podrían estar en un estado indeterminado. Esto podría causar problemas imprevistos cuando el programa sigue funcionando.

En su mayoría, creo, estos problemas se relacionan con la API de consola. Como se ha mencionado, AllocConsole no funciona desde este punto en adelante (se colgará la aplicación), por lo que el programa no puede abrir una nueva consola. Es muy posible que otras funciones de la consola fallarán también. Básicamente, cualquier cosa que haga a partir de ese punto en adelante que de ninguna manera (directa o indirectamente) pone en Kernel32 está sujeto a un comportamiento indefinido, pero sospecho que en la práctica no habrá ningún problema fuera de las funciones de la consola.

Mi conclusión es que se debe evitar este método si es posible, pero si la terminación prematura es peor, entonces esto puede ser considerado como una emergencia solución temporal, para ser utilizado con moderación y con cuidado.

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