2011-01-18 21 views
9

Tengo una situación en la que estoy iniciando un proceso en mi código para configurar un canal de IPC. El proceso que estoy iniciando es una aplicación MFC sin soporte CLR. La aplicación desde la cual estoy comenzando este proceso es un módulo C# en una aplicación WPF (pensé que no creo que eso sea consecuente con mi problema). Esto funciona con una versión de la aplicación que admite CLR, y funciona en todas las computadoras excepto en el destino de despliegue, una computadora con pantalla táctil con Windows 7. Pero por alguna razón, cuando lo intento con este escenario exacto, el objeto Proceso nunca resuelve un identificador de ventana principal (Process.MainWindowHandle). ¿Hay otro método (quizás incluso pinvoke) de hacer esto? ¿Esto es algo de seguridad? Soy el único que mira el proceso. El controlador de ventana principal del proceso existe. No veo lo que podría estar mal.¿Por qué no se puede obtener el identificador de la ventana principal para un proceso iniciado?

Si ayuda, este es mi código.

 _applicationProcess = new Process(); 
     _applicationProcess.StartInfo.FileName = _strProcessPath; 
     _applicationProcess.StartInfo.Arguments = _strProcessArguments; 
     _applicationProcess.Start(); 

     long nTicks = Environment.TickCount; 
     if (_applicationProcess.WaitForInputIdle(1 /*minute(s)*/ * 60000)) 
     { 
      try 
      { 
       do 
       { 
        // Don't let total processing take more than 1 minute(s). 
        if (Environment.TickCount > nTicks + 1 /*minute(s)*/ * 60000) 
         throw new ApplicationException("MFCApplication.Startup failed! The main window handle is zero!"); 

        _applicationProcess.Refresh(); 
       } 
       while (_applicationProcess.MainWindowHandle.ToInt32() == 0); 

       _applicationHandle = new IntPtr(_applicationProcess.MainWindowHandle.ToInt32()); 
      } 
      catch (Exception ex) 
      { 
       //Do some stuff... 
       throw; 
      } 
     } 
     else 
     { 
      // Do exception handling. 
     } 

El ApplicationException es golpeado después de un minuto de tratar de conseguir una manija de la ventana principal distinto de cero.

+1

¿Ha cansado de usar 'WaitForInputIdle' como lo sugieren los documentos de MSDN? También es una buena práctica usar 'throw' en lugar de' throw ex', ya que perderá la información de seguimiento de pila con 'throw ex' (' throw ex' reinicia el lanzamiento de excepción y, por lo tanto, el seguimiento de pila). –

+0

Revisa las ediciones. :) – Jordan

+0

@jordan veo tu edición. Debe incluir @nombre de usuario en sus comentarios para que se notifique al otro usuario al que está respondiendo. –

Respuesta

6

Desafortunadamente, el valor que obtiene de Process.MainWindowHandle es una suposición. No hay función API disponible para un programa que le permite decirle a Windows "esta es mi ventana principal". La regla que usa está documentada, es la primera ventana que crea un proceso cuando se inicia. Eso causa problemas si esa primera ventana es, por ejemplo, una ventana de inicio de sesión o una pantalla de bienvenida.

No hay mucho que pueda hacer al respecto, debe saber más acerca de cómo se comporta el programa para encontrar esa ventana real principal. La enumeración de ventanas con EnumThreadWindows() podría ayudarlo a encontrarlo, siempre que la primera ventana se haya creado con el mismo hilo que la ventana principal. Un EnumWindows() más elaborado será necesario si ese no es el caso.

3

Mi costumbre es llamar a EnumWindows en un ciclo combinado con GetWindowThreadProcessId para encontrar el identificador de ventana.

C Code, adapt to your language 


DWORD TargetHWND; 

//... 
    while (EnumWindows(EnumWndProc, (LPARAM)(DWORD)pid)) { 
     Sleep(100); 
    } 


//... 

BOOL EnumWndProc(HWND hWnd, LPARAM lParam) { 
    DWORD pid = (DWORD)-1; 
    GetWindowThreadProcessId(hWnd, &pid); 
    if (pid == (DWORD)lParam) { 
     TargetHWND = hWnd; 
     return FALSE; 
    } 
    return TRUE; 
} 
+0

¿Cómo me ayuda esto exactamente? Estoy tratando de obtener un identificador de ventana de otro proceso. ¿Me puede dar algún código? – Jordan

+0

Así que, básicamente, esto hace que todas las ventanas para el ID de proceso dado sean interesantes. – Jordan

1

No sé por qué podría ser diferente, pero después de crear el proceso, trata de hacer:

Process[] allProcesses = Process.GetProcessesByName("YourWindowTitle"); 

y ver si alguno de los procesos devueltos tienen un MainWindowHandle.

+0

Es diferente, pero en el sentido opuesto. Al hacerse cargo de un proceso de esta manera, no tiene plena confianza y, por lo tanto, no puede hacer gran cosa con él y, desde luego, no obtener su control. Solo cuando comienzas un proceso puedes interactuar con él en cualquier sentido significativo. – Jordan

2

el fin de obtener MainWindowHandle por medio de su proceso, por favor asegúrese de que su aplicación de WPF se muestra en la barra de tareas es decir ShowInTaskbar="True" y establecer Application.Current.MainWindow propiedad a la ventana que desea establecer como ventana principal.

Si ejecuto el código a continuación en mi ventana principal de WPF sin configurar ShowInTaskbar="True" siempre obtuve 0 como MainWindowHandle porque mi ventana WPF era de pantalla completa y no se muestra en la barra de tareas.

Application.Current.MainWindow = this; 
    var Query = System.Diagnostics.Process.GetProcessesByName("ProcessName"); 

    if (Query.Any()) 
    { 
     Query.FirstOrDefault().Refresh(); 
     MessageBox.Show(Query.FirstOrDefault().MainWindowHandle.ToInt32().ToString()); 
    } 
Cuestiones relacionadas