Título: Wait For Application To Load Publicado por: TrashAmbishion en 5 Septiembre 2016, 06:04 am Hola,
Quería saber sobre el funcionamiento de este Snippet publicado por Elektro para esperar a que una aplicación termine de cargar.. Código
Necesito verificar los modulos de ese proceso una vez que termine de cargar.. pero no me funciona me devuelve menos modulos de los esperados.. Gracias de antemano Título: Re: Wait For Application To Load Publicado por: TrashAmbishion en 5 Septiembre 2016, 20:28 pm Resolví una posible variante del Snippet
http://stackoverflow.com/questions/15906479/execute-a-application-and-wait-for-it-to-be-loaded Después reviso a mas profundidad pero hice una prueba rápida y funcionó, lo que me parece es que el programa mucho antes de que caer en un estado de tranquilidad ya hizo la carga todos los módulos que en mi caso con 100... Salu2 Título: Re: Wait For Application To Load Publicado por: Eleкtro en 5 Septiembre 2016, 22:45 pm Ese código es muy antiguo y es una guarrada (todo hay que decirlo), yo no lo escribí: http://stackoverflow.com/a/15906638/1248295 (http://stackoverflow.com/a/15906638/1248295)
El algoritmo de ese código se basa en la comparación de ciertos parámetros de consumo del proceso para determinar si el proceso está "inactivo". Cada 1500 milisegundos, mediante un Timer, comprueba si ha habido un incremento en el tamaño de alojamiento de memoria privada del proceso, y el tiempo de ejecución en modo kernel. Cuando inicias un proceso se disparan muchos parámetros, entre ellos los que ya he mencionado, y cuando la interfáz de usuario del proceso se ha cargado completamente, los valores de esos parámetros dejan de incrementar (o al menos deberían, los bugs y/o fugas de memoria serían una excepción, jeje), y en ese preciso momento podemos concluir (aunque no en todos los casos) que la interfaz de usuario se ha cargado por completo, por que no está gastando más recursos. No existe una ciencia ni botón mágico con el que poder determinar cuando la interfaz de usuario de un proceso externo se ha cargado completamente, de hecho hay interfaces de usuario llenas de animaciones que siempre están generando recursos (como por ejemplo el cliente de Battle.net de Blizzard) y eso es un problema muy grande para hacer nuestros cálculos. En .NET podemos hacer uso del método Process.WaitforInputIdle() pero esto es una metología engañosa, puesto que solo sirve para esperar a que la cola de mensajes de la aplicación entre en un estado Idle, es decir, cuando esté lista para recibir mensajes de entrada, el problema es que muchas aplicaciones (como or ejemplo Steam) entran en ese estado mientras está cargando la UI ...mucho antes, durante la etapa de startup. Bueno, despues de todo este rollo que he soltado para explicar varios aspectos, vamos a lo que te interesa, el código: En el código fuente de mi API gratuita ElektroKit puedes encontrar una refactorización que le hice a esa guarrada de código que publiqué en su día, estoy seguro que te será mucho más sencilla de entender: (http://i.imgur.com/aH0EmiQ.png) Cita de: https://github.com/ElektroStudios/ElektroKit/blob/master/Solution/Elektro.Processes/Tools/ProcessUtil.vb Código
De hecho, cualquier sippet mio que encuentres en el foro probablemente con el paso del tiempo lo haya mejorado e integrado en ElektroKit, solo tienes que buscar por el nombre de la función, o preguntarme. Hoy me he tomado un rato para volver a refactorizar el código, no me convencia demasiado la manera de usarlo, así que he decidido convertirlo en extensiones de método, y he implementado una lógica basada en WMI, ¿por qué?, por que aparte de servirnos para analizar mayor cantidad de parámetros como por ejemplo la cantidad de operaciones de transferencia de lectura/escritura del proceso, además nos sirve para evitar conflictos al intentar leer los parámetros de un exe de 64-bits desde un exe de 32 Bits ...en caso de que lo necesitemos. En fin, aquí tienes el código (le he eliminado la documentación Xml no-esencial para que no ocupe demasiado espacio): Código
Ejemplos de uso sincrónico: Código
Ejemplos de uso asincrónico: Código
lo que me parece es que el programa mucho antes de que caer en un estado de tranquilidad ya hizo la carga todos los módulos que en mi caso con 100... Como ya te dije no existe una ciencia con la que predecir la carga completa de la UI, yo te recomiendo usar un valor de entre 1000 a 2000 ms para el parámetro "checkInterval" de los códigos de arriba (en el código que tú pusiste de Stackoverflow también), si usas un valor como 100 ms no es nada bueno, creeme, si el PC está haciendo muchas tareas e intentas iniciar un proceso entonces la información del proceso (me refiero al objeto Process, y la información de WMI), tardará mucho más que 100 ms en actualizarse, y esto quiere decir que los valores que obtendrás en la siguiente iteración serán idénticos así que la comprobación de valores te podría dar un falso positivo, y te lo daría. En otras palabras, cuanto mayor sea el intervalo de ms que especifiques, más seguro será la comprobación. Un saludo Título: Re: Wait For Application To Load Publicado por: TrashAmbishion en 6 Septiembre 2016, 21:08 pm Muchas gracias lo revisaré...
Salu2 Pd: Ya estoy a punto de poner a prueba el proyecto y quería saber (para cubrir dudas) que como obligatoriamente para poder jugar el juego tiene que ser a traves de mi programa tendría cierta ventaja como por ejemplo bloquear el proceso del juego para que nada mas que mi programa acceda a el, estuve mirando "mutex" pero creo que no tiene nada que ver, y lo otro es iniciarlo de forma que no se pudiera listar en los procesos como un rootkit, pero que la GUI si se mantuviera o cualquier otro invento No obstante El injector que estoy mirando, trae una función para oculta la DLL que injecta.. pero esa DLL requiere otra DLL que si se carga y ahi pita mi programa, pero pasa que hay programas que sirven para hacer capturas del juego o grabar incluso hasta el IDM a veces mete una DLL en las del juego.. Estaba pensado hacer una lista de las DLL que carga en un sistema virgen y entonces de ahi ir partiendo revisar las que esten de mas, hacerle unload si hay algo sospechoso.. que crees ? Salu2 Título: Re: Wait For Application To Load Publicado por: Eleкtro en 7 Septiembre 2016, 09:50 am quería saber (para cubrir dudas) que como obligatoriamente para poder jugar el juego tiene que ser a traves de mi programa tendría cierta ventaja como por ejemplo bloquear el proceso del juego para que nada mas que mi programa acceda a el, estuve mirando "mutex" pero creo que no tiene nada que ver, y lo otro es iniciarlo de forma que no se pudiera listar en los procesos como un rootkit, pero que la GUI si se mantuviera o cualquier otro invento Bueno, en mi opinión no está del todo claro lo que dices, si tu programa debería ser el único que pudiera INICIAR el executable, o por otro lado el único que pudiera ACCEDER a él, o ambas cosas. Si te refieres a imposibilitar que el usuario pueda iniciar el exe del juego: Puedes hacer un API hooking a la función CreateProcessW/CreateProcessA para interceptar las lalmadas a dicha función y anular la llamada en caso de que el parámetro lpApplicationName corresponda con el exe del juego. En .NET puedes implementar técnicas de API Hooking de forma relativamente sencilla con la librería Deviare: http://www.nektra.com/products/deviare-api-hook-windows/ (http://www.nektra.com/products/deviare-api-hook-windows/). Un ejemplo de implementación que escribí:
Otra opción para llevar a cabo lo mismo sería monitorizar la ejecución de nuevos procesos mediante WMI, lo que practicamente no costaría nada de esfuerzo implementarlo, sin embargo, WMI necesita un mínimo de tiempo para actualizarse y detectar nuevos procesos en la lista de procesos interna del sistema, dicho de otra forma: es una metodología mucho menos sensible que el API hooking. En mi API gratuita ElektroKit tienes un ejemplo de implementación: (http://i.imgur.com/2vH8dpZ.png)
Pero como ya he explicado WMI es lento, así que sería mejor usar un Timer (de verdad, da muchos mejores resultados que WMI): (http://i.imgur.com/JQcgCLS.png)
Notas adicionales: - Si quieres imposibilitar más de una instancia del executable entonces puedes usar un MUTEX o semáforo, no te va a servir para otra cosa en este propósito. - Si, puedes ocultar el nombre del exe del juego en el administrador de tareas, puedes hacerlo mediante la metodología tradicional y casi obsoleta de la Win32 API (FindWindow + EnumChildWindows + etc) o también mediante el framework de Windows UI Automation de la librería de classes de .NET Framework, pero no te aconsejo ocultar el nombre del proceso de ninguna forma, puesto que se requiere mucho trabajo para cada versión de Windows necesitarás hacer cambios en los nombres de las classes y etc, te llevaría bastante tiempo solo en investigar los nombres haciéndole un Spy al taskmanager, vaya. No se si existe otra forma para ocultarlo. Si te refieres a impedir que el usuario pueda utilizar la ventana del proceso: Mediante la API RAWINPUT puedes registrar un dispositivo de teclado y/o mouse virtual y solo lo usuarias tú, pero requiere mucho trabajo, mucho p/invoking:
Cabe mencionar que puedes utilizar la función Win32 BlockInput para imposibilitar el uso del teclado y el mouse, pero lamentablemente esto afectaría de forma global al usuario, no solo a la ventana del juego. Se me ocurre que podrías registrar un mensaje de ventana, e intentar bloquear la cola de mensajes de la ventana del juego para que solo acepte tu mensaje, supongo que esto es lo que harán los bots más sofisticados (como los Buddy bots de los juegos de Blizzard) pero solo es una hipótesis o una conjetura, realmente no estoy nada seguro de como se implementaría esta técnica. que crees ? La inyección de código en video juegos y en general estas cosas para juegos no es lo mio, te podrían orientar mejor en el foro de ingenieria inversa, supongo.Saludos Título: Re: Wait For Application To Load Publicado por: FJDA en 7 Septiembre 2016, 13:43 pm una forma sencillita sería esta
Código
__________________________________________________________ y se puede usar HasExited de forma análoga para saber si la aplicación se ha cerrado. Devuelve True. |