Red de conocimiento informático - Material del sitio web - Cómo controlar el programa de la consola para salir en el servicio de Windows

Cómo controlar el programa de la consola para salir en el servicio de Windows

Cómo controlar el programa de la consola para salir en el servicio de Windows

En primer lugar, es relativamente fácil controlar los servicios de Windows. Hay muchos ejemplos ya preparados.

SYNtService es un buen ejemplo.

Es muy fácil controlar la salida de una ventana y PostMessage puede solucionar el problema.

Existen muchos métodos ya preparados para controlar la salida de la consola. Métodos más comunes:

1. TerminateProcess

El método más original y violento para forzar la salida de la consola. El proceso de la consola se desbordó sin ninguna posibilidad de defenderse. Pero espero que la consola al menos pueda soportar las "consecuencias" antes de lanzarla.

2. señal/subir

Resulta que Windows también tiene señal, pero matar se reemplaza por subir. Pero en comparación con la función de señal de la serie Unix, está muy por detrás. Y una cosa problemática es que el aumento solo puede tener efecto en esta consola, no en el proceso especificado.

Puede especificar una función de devolución de llamada en la señal. Cuando reciba SIGINT/SIGTERM o similar, maneje el asunto y luego notifique a cada hilo para que finalice.

Dado que no se pueden iniciar otros procesos, ¿esta función queda inutilizable? De hecho, puedes considerar CreateRemoteThread y luego generarlo en los procesos de otras personas...

3. SetConsoleCtrlHandler / GenerateConsoleCtrlEvent

Esta es la consola especialmente utilizada para manejar Ctrl-C/. Ctrl-Break/ y Cómo manejar eventos de cierre de Windows, etc. Más potente que la señal. Y está escrito en la descripción que se pueden procesar otros procesos (y también se pueden procesar grupos de procesos). En palabras de Internet, es: ¡muy femenino, muy elegante!

Sin embargo, tenga en cuenta que si desea procesar el proceso hijo creado por él, debe utilizar el indicador CREATE_NEW_PROCESS_GROUP al crear el proceso hijo. Otro punto que está escrito en el documento es que el proceso debe tener una ventana de consola. De lo contrario, llamar a GenerateConsoleCtrlEvent devolverá 6 y dirá ERROR_INVALID_HANDLE.

Aquí viene el problema. El servicio en sí no tiene una ventana de consola. El proceso hijo creado por el servicio debe tener su propia ventana. Pero, en general, por motivos de apariencia, el proceso iniciado por el Servicio no quiere tener una ventana. Eso significa que el proceso hijo no tiene ventana de consola y GenerateConsoleCtrlEvent falla.

Revisé mucha información en Internet (¿cómo es que no vi nada muy pornográfico o violento?), entre los cuales Louis K. Thomas mencionó un método en SendSignal , que consiste en obtener la entrada de kernel32!CtrlRoutine y luego usar el método CreateRemoteThread para permitir que la consola remota ejecute kernel32!CtrlRoutine. Pero hay un problema con este método. Al obtener kernel32! CtrlRoutine, también se utiliza GenerateConsoleCtrlEvent para obtenerlo. Sin embargo, el Servicio en sí no tiene una ventana de consola y se produce un error cuando se llama a GenerateConsoleCtrlEvent.

Otro artículo del grupo de discusión de Google menciona que primero puedes AllocConsole, luego GenerateConsoleCtrlEvent, luego FreeConsole... Entonces la solución es:

En servicio:

p>

Primero AllocConsole

Luego use GenerateConsoleCtrlEvent para obtener kernel32!CtrlRoutine

Luego FreeConsole

Cuando necesite finalizar el proceso, llame a CreateRemoteThread y coloque el código kernel32 !CtrlRoutine se inyecta en el proceso secundario para su ejecución

De esta manera, nadie puede ver la ventana de la consola (AllocConsole en el servicio es muy rápido y la ventana no se puede ver, e incluso se sospecha que hay ninguna ventana). Al mismo tiempo, puede notificar al proceso secundario para que salga correctamente.

Hay un problema: si mi máquina se inicia como servidor, es decir, no entra en el estado de inicio de sesión, no sé si habrá algún problema con el Servicio iniciado de esta manera. .No he tenido tiempo de probarlo todavía.