.NET (C #): ¿Obtiene ventanas secundarias cuando solo tiene un identificador de proceso o PID?

Tipo de un problema de caso especial:

  • Comienzo un proceso con System.Diagnostics.Process.Start(..)
  • El proceso abre una pantalla de presentación: esta pantalla emergente se convierte en la ventana principal.
  • La pantalla de bienvenida se cierra y se muestra la IU “real”. La ventana principal (pantalla de bienvenida) ahora no es válida.
  • Todavía tengo el objeto Process, y puedo consultar su manejador, módulo, etc. Pero el manejador de la ventana principal ahora no es válido.

Necesito obtener la interfaz de usuario (o IU) del proceso en este punto. Supongamos que no puedo cambiar el comportamiento del proceso para hacer esto más fácil (o más sano).

He buscado en línea pero admito que no lo busqué durante más de una hora. Parecía que debería ser algo trivial 🙁

Si no le importa usar la API de Windows, puede usar EnumWindowsProc y comprobar cada uno de los identificadores que aparecen usando GetWindowThreadProcessId (para ver que está en su proceso), y luego tal vez IsWindowVisible , GetWindowCaption y GetWindowTextLength para determinar qué hWnd en tu proceso es el que quieres.

Aunque si no has usado esas funciones antes de ese enfoque será un dolor correcto, así que con suerte hay una manera más simple.

@ageektrapped está en el camino correcto, sin embargo, FindWindow no buscará las ventanas secundarias.

Para eso, necesitará usar FindWindowEx

Gracias por sus respuestas. Gracias a ti aquí, descubrí cómo saber si la ventana principal de un proceso está delante o no:

NB: por supuesto esto necesita System.Diagnostic y System.Runtime.Interrop

 public bool IsWindowActive(Int32 PID) { return IsWindowActive(Process.GetProcessById(PID)); } [DllImport("user32.dll")] private static extern IntPtr GetForegroundWindow(); public bool IsWindowActive(Process proc) { proc.Refresh(); return proc.MainWindowHandle.Equals(GetForegroundWindow()); } 

Puede encontrar que si llama a .Refresh () obtiene la nueva ventana de nivel superior.

Si conoce el título de la ventana, puede usar la llamada Win32, FindWindow, a través de P / Invoke.

Puedes encontrar la firma aquí en pinvoke.net

Por lo que entiendo, la propiedad MainWindowHandle del proceso que está iniciando no es válida. Si ese es el caso, puede usar la función FindWindow (desde Win32 SDK) que devuelve el manejador de ventana que necesita. Todo lo que necesita es el nombre de clase de la ventana principal de la aplicación de destino. Puedes obtenerlo usando Spy ++ o Winspector . También debe asegurarse de tener la ventana correcta al verificar el ID de proceso de la ventana usando GetWindowThreadProcessId .

Por último, debo decir que no soy un experto en Win32 y que podría haber una mejor solución para su caso.

Use Process.GetProcessById (proc.Id); donde proc era tu pantalla de inicio. Funciona para mi.

Ahora, ¿cómo llegar a las propiedades de la ventana principal en System.Windows.Forms para darle un enfoque sin usar win32? Después de todo, se supone que .net es una solución integral, ¿no es así?

En algún lugar del código, se crea la ventana principal “real”. Puede guardar el identificador de ventana en ese momento y luego, una vez que se cierre la pantalla de bienvenida, puede establecer Application.MainWindow en la ventana real.

La propiedad MainWindowHandle se almacena en caché después de que se accedió por primera vez, por lo que no la ve cambiar incluso después de que el identificador no sea válido. La información de GregUzelac es correcta. Llamar a Proces.Refresh hará que la siguiente llamada a Process.MainWindowHandle vuelva a hacer la lógica para encontrar un nuevo manejador de ventana principal. La lógica de Michael también funciona porque el nuevo Proceso no tiene una versión en caché de MainWindowHandle.