it-swarm-es.tech

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

Tipo de problema de caso especial:

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

Necesito obtener la interfaz de usuario del proceso (o identificador de interfaz de usuario) en este punto. Suponga 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 busqué más de una hora. Parecía que debería ser algo trivial :-(

22
shea241

Si no le importa usar la API de Windows, puede usar EnumWindowsProc , y verificar cada uno de los controladores que aparecen usando GetWindowThreadProcessId (para ver que está en su proceso), y luego tal vez IsWindowVisible, GetWindowCaption y GetWindowTextLength para determinar cuál hWnd en su proceso es el usted quiere.

Aunque si no ha utilizado esas funciones antes, ese enfoque será un verdadero dolor, entonces espero que haya una manera más simple.

11
MB.

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

Para eso necesitarás usar FindWindowEx

7
Ash

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

N.B: 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());
}
3
Giova

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

2
GregUzelac

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

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

1
Michael Lastufka

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

Puede encontrar la firma aquí en pinvoke.net

1
ageektrapped

Por lo que entiendo MainWindowHandle propiedad del proceso que está iniciando no es válida. Si ese es el caso, puede usar la función FindWindow (del Win32 SDK) que devuelve el identificador de ventana que necesita. Todo lo que necesita es el nombre de la clase de la ventana principal de la aplicación de destino. Puede obtenerlo usando Spy ++ o Winspector . También debe asegurarse de tener la ventana correcta comprobando la identificación del proceso de esa 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.

1
blackwing

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

0
Matt Ellis

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

0
Marcus Erickson