C# – Conseguir un Handler a la Ventana de un Proceso
April 18th, 2010 by JuanK
Cuando se esta jugando con la API de Windows, especialmente con el tema de las ventanas esta función puede resultar de muchÃsima utilidad. Sin embargo no existe, asà que hay que implementarla.
En resumen explicare los pasos necesarios para crear una función GetProcessWindowHandler, la cual devuelve un handler a la ventana principal de un proceso.
Necesitaremos recuperar el handler de la ventana (cuando la encontremos),asà que creare una clase que utilizare como LPARAM a algunas funciones de la API, capaz de contener tanto el id del proceso como el handler de la ventana.
/// <summary>Almacena el ID de proceso y el handler de una ventana</summary>
private class AuxInfo
{
public int processID;
public IntPtr handler;
}
Para lograrlo debemos recurrir a la función EnumWindows, la utilizaremos para recorrer las ventanas existentes en búsqueda de una ventana cuyo id de proceso coincida con el proceso que acabamos de iniciar.
Como EnumWindows requiere como parámetro un delegado que se ejecutara para las ventanas enumeradas, entonces la función de búsqueda debe tener el signature de EnumWindowsProc, declarado en la API de Windows y que acá lo declararo como un delegado.
/// <summary>
/// Delegado para hacer de callback
/// </summary>
/// <param name="hwnd" />handler de la ventana
/// <param name="lParam" />paramétro con la informacion necesaria para el proceso
/// <returns>Valor de retorno del proceso</returns>
private delegate bool EnumWindowsProc(IntPtr hwnd, AuxInfo lParam);
Y acá la definición de EnumWindows
/// <summary>
/// Recorre las ventanas y ejecuta un proceso para cada una de ellas
/// </summary>
/// <param name="lpEnumFunc" />Delegado con el proceso a utilizar para cada ventana
/// <param name="lParam" />paramétro con la informacion necesaria para el proceso
/// <returns>Retorna true si se recorren todas las ventanas, de lo contrario false o segun determine el usuario a trabes del callback</returns>
[DllImport("user32.dll")]
private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, AuxInfo lParam);
Para poder determinar el id de proceso de cada una de las ventanas enumeradas haré uso de GetWindowThreadProcessId:
/// <summary>
/// Devuelve el ID del proceso al que pertenece el hilo de la ventana
/// </summary>
/// <param name="hwnd" />handler de la ventana
/// <param name="lpdwProcessId" />ID del proceso (parámetro de salida)
/// <returns>ID del Thread que creó la ventana</returns>
[DllImport("user32.dll")]
private static extern uint GetWindowThreadProcessId(IntPtr hwnd, out int lpdwProcessId);
Ya con esta información mi función delegada para encontrar el handler de ventana ( la que se ejecutara por cada ventana hallada por EnumWindows )es esta:
/// <summary>
/// Obtiene el handler de la ventana asociada a un proceso
/// Este procedimiento es solo de utileria para usarse con EnumWindows
/// y no deberia ser invocado directamente
/// </summary>
/// <param name="hwnd" />handler de la ventana actual
/// <param name="info" />informacion auxiliar para el proceso
/// <returns>false si encuentra la ventana, true sino</returns>
private static bool _GetProcessWindowHandler(IntPtr hwnd, AuxInfo info)
{
int processID;
GetWindowThreadProcessId(hwnd, out processID);
if (processID == info.processID)
{
info.handler = hwnd;
return false;
}
else
{
info.handler = IntPtr.Zero;
return true;
}
}
Estando ya definida mi función de callback entonces llamaré a EnumWindows y crearé con ella una función GetProcessWindowHandler, la cual como su nombre lo indica será la que usaré para devolver el handler de la ventana del proceso. Sin embargo el tema no es tan fácil como pareciera a simple vista.
Si utilizo la función para traer un handler a la ventana de un proceso ya abierto no tengo ningún problema, pero si el proceso recién lo estoy lanzando desde mi aplicación, por ejemplo con Process.Start(), se debe esperar a que el sistema operativo cree y muestre por primera vez la ventana, de lo contrario no habrá manera de hallarla con EnumWindows, asà que debo llamar a EnumWindows hasta que se cumplan estas dos condiciones:
-
Encontró una ventana asociada al proceso
-
Dicha ventana ya ha sido mostrada por el sistema operativo
Para la primera condición, y de acuerdo a como creamos nuestra función de callback (_GetProcessWindowHandler), basta con preguntar si el handler es válido y para la segunda se debe determinar si la ventana de dicho proceso ya ha sido mostrada lo cual lo hacemos con IsWindowVisible:
/// <summary>
/// Indica si una ventana es o no visible
/// </summary>
/// <param name="hWnd" />handler de la ventana
/// <returns>Indicador de si la v entana es o no visible</returns>
[DllImport("user32.dll")]
private static extern bool IsWindowVisible(IntPtr hWnd);
Asà que la función internamente debe tener un proceso iterativo para poder hallar el handler
/// <summary>
/// Devuelve el handler de la ventana asociada al proceso
/// </summary>
/// <param name="pid" />Id del proceso
/// <returns>handler de la ventana</returns>
public static IntPtr GetProcessWindowHandler(int pid)
{
//Delegado con el proceso auxiliar de búsqueda
EnumWindowsProc getHandlerVentana = new EnumWindowsProc(_GetProcessWindowHandler);
//Informacion auxiliar
AuxInfo informacion = new AuxInfo();
informacion.processID = pid;
/*Repetir bucle hasta que este presente la ventana del proceso
*(puede que la enumeracion se realice y windows aún no haya creado
*la primera ventana del proceso o bien no la haya hecho visible,
*por lo cual se debe repetir el bucle hasta encontrala)*/
do
{
/*Enumerar las ventanas buscando la que coincida con
*el id de proceso contenido en informacion */
EnumWindows(getHandlerVentana, informacion);
} while (informacion.handler == IntPtr.Zero || !IsWindowVisible(informacion.handler));
return informacion.handler;
}
Bien, he encapsulado la funcionalidad en la clase Win32APITools y el método GetProcessWindowHandler es el único método expuesto, asi que la implementación completa queda asÃ:
using System;
using System.Runtime.InteropServices;
class Win32APITools
{
/// <summary>Almacena el ID de proceso y el handler de una ventana</summary>
private class AuxInfo
{
public int processID;
public IntPtr handler;
}
/// <summary>
/// Delegado para hacer de callback
/// </summary>
/// <param name="hwnd" />handler de la ventana
/// <param name="lParam" />paramétro con la informacion necesaria para el proceso
/// <returns>Valor de retorno del proceso</returns>
private delegate bool EnumWindowsProc(IntPtr hwnd, AuxInfo lParam);
/// <summary>
/// Recorre las ventanas y ejecuta un proceso para cada una de ellas
/// </summary>
/// <param name="lpEnumFunc" />Delegado con el proceso a utilizar para cada ventana
/// <param name="lParam" />paramétro con la informacion necesaria para el proceso
/// <returns>Retorna true si se recorren todas las ventanas, de lo contrario false o segun determine el usuario a trabes del callback</returns>
[DllImport("user32.dll")]
private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, AuxInfo lParam);
/// <summary>
/// Devuelve el ID del proceso al que pertenece el hilo de la ventana
/// </summary>
/// <param name="hwnd" />handler de la ventana
/// <param name="lpdwProcessId" />ID del proceso (parámetro de salida)
/// <returns>ID del Thread que creó la ventana</returns>
[DllImport("user32.dll")]
private static extern uint GetWindowThreadProcessId(IntPtr hwnd, out int lpdwProcessId);
/// <summary>
/// Indica si una ventana es o no visible
/// </summary>
/// <param name="hWnd" />handler de la ventana
/// <returns>Indicador de si la v entana es o no visible</returns>
[DllImport("user32.dll")]
private static extern bool IsWindowVisible(IntPtr hWnd);
/// <summary>
/// Obtiene el handler de la ventana asociada a un proceso
/// Este procedimiento es solo de utileria para usarse con EnumWindows
/// y no deberia ser invocado directamente
/// </summary>
/// <param name="hwnd" />handler de la ventana actual
/// <param name="info" />informacion auxiliar para el proceso
/// <returns>false si encuentra la ventana, true sino</returns>
private static bool _GetProcessWindowHandler(IntPtr hwnd, AuxInfo info)
{
int processID;
GetWindowThreadProcessId(hwnd, out processID);
if (processID == info.processID)
{
info.handler = hwnd;
return false;
}
else
{
info.handler = IntPtr.Zero;
return true;
}
}
/// <summary>
/// Devuelve el handler de la ventana asociada al proceso
/// </summary>
/// <param name="pid" />Id del proceso
/// <returns>handler de la ventana</returns>
public static IntPtr GetProcessWindowHandler(int pid)
{
//Delegado con el proceso auxiliar de búsqueda
EnumWindowsProc getHandlerVentana = new EnumWindowsProc(_GetProcessWindowHandler);
//Informacion auxiliar
AuxInfo informacion = new AuxInfo();
informacion.processID = pid;
/*Repetir bucle hasta que este presente la ventana del proceso
*(puede que la enumeracion se realice y windows aún no haya creado
*la primera ventana del proceso o bien no la haya hecho visible,
*por lo cual se debe repetir el bucle hasta encontrala)*/
do
{
/*Enumerar las ventanas buscando la que coincida con
*el id de proceso contenido en informacion */
EnumWindows(getHandlerVentana, informacion);
} while (informacion.handler == IntPtr.Zero || !IsWindowVisible(informacion.handler));
return informacion.handler;
}
}
Y este es un ejemplo de uso:
using System;
using System.Diagnostics;
namespace GetProcessWindowHandler
{
class Program
{
static void Main(string[] args)
{
Process proc = new Process();
ProcessStartInfo psi = new ProcessStartInfo("calc.exe");
proc.StartInfo = psi;
proc.Start();
IntPtr handler = Win32APITools.GetProcessWindowHandler(proc.Id);
Console.WriteLine("El Handler obtenido para la ventana de este proceso es: {0}", handler);
Console.ReadLine();
}
}
}
Hasta Pronto.
- 5 Comentarios »
- Publicado en la categoría 'C#'

Wordpress
5 comentarios to “C# – Conseguir un Handler a la Ventana de un Proceso ”
October 3rd, 2009 at 9:42 pm
[...] Otro Post en Ideas de un Conejo [...]
October 3rd, 2009 at 9:50 pm
[...] Otro Post en Ideas de un Conejo [...]
October 3rd, 2009 at 10:02 pm
[...] http://juank.black-byte.com/c-conseguir-handler-ventana-proceso/ [...]
October 4th, 2009 at 11:54 pm
Hola como estas, ante todo un plazer mi nombre es Edgar, y te encontre por uno de los tantos foros que hay en la red en este caso el de Laneros que es muy bueno y reconocido por las personas.
Me comunico contigo porque de verdad necesito tu ayuda con un programa que necesito crakear o no se modificar de alguna forma para que me deje de ser una version DEMO, y la verdad no se a quien acudir tal vez tengas conocimientos de como hacerlo o conoceras a alguien que podria ayudarme, te dejo informacion al respecto.
Busque por todos lados: GOOGLE, E-MULE, ARES, UTORRENT, e incluso muchisimas paginas de Crak y Keygens, sobre un programa que se llama: ASTER.
Descripcion del Programa: Este programa Permite que en 1 sola pC puedan trabajar 2 usuarios o personas al mismo tiempo.
Hay programas similares como son el llamado BETWIN Y Softxpand, pero no me funcionan correctamente en mi pc.
La pagina de los creadores del programa Aster es:
http://international.ibik-soft.com/content/view/39 De la misma puedes decargar la version que me funciono perfectamente en mi pc se llama: Download ASTER XP 4.5T (10 days free trial)
Pero solo dura 10 dias, y yo la verdad no tengo recursos para cancelar por ello busco la forma de obtener un crak u otro tipo de solucion.
La idea seria buscar la forma de modificar el instalador original del programa, para que al momento de instalarlo en la maquina salte el paso de validacion de contraseña, como todo programa que suele mostrar un menu donde dice: trial un boto, otro para meter la key y otro para comprar todo. Si se lograra buscar la forma de alterar ese algoritmo del programa saltar ese paso y desactivar ese contador la verdad agradeceria.
Es el unico programa que me ha venido funcionando bien y no encuentro solucion con un crak en ningun lado.
Gracias de antemano.
Att. Edgar
Cualquier cosa en que pueda ayudar avisame….
November 3rd, 2009 at 2:53 am
Me llamaron mucho la atencion tus comentarios y me ayudaron mucho….ahora mismo quiero encontrar la manera de preguntarle a Juan Carlos Ruiz Pacheco unas dudas, porque econtre en la red unos temas de el y creo que podria ayudarme….
por favor orientame de alguna manera porqeu no encuentro ninguna manera de dar con el….
gracias