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
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.