2010-09-24 34 views
9

Estoy usando la automatización para probar una aplicación, pero a veces quiero iniciar la aplicación a través de un archivo por lotes. Cuando ejecuto "process.WaitForInputIdle (100)" aparece un error:¿Cómo puedo saber si un proceso tiene una interfaz gráfica?

"FallForInputIdle failed. Esto podría deberse a que el proceso no tiene una interfaz gráfica".

¿Cómo puedo saber si el proceso tiene una interfaz gráfica o no?

Respuesta

6

Ver Environment.UserInteractive. Eso identificará si el proceso tiene una interfaz en absoluto, p. los servicios no son interactivos con el usuario.

También puede consultar Process.MainWindowHandle que le dirá si hay una interfaz gráfica.

Una combinación de estos dos controles debe abarcar todas las posibilidades.

+0

Desafortunadamente, los archivos de proceso por lotes parecen ser interactivos por el usuario (esto devuelve "verdadero" tanto para el archivo por lotes como para la ventana). – Lunivore

+0

Cuando dice que Process.MainWindowHandle se podría usar para hacer esto, ¿cómo? Mente ponerlo en otra respuesta? – Lunivore

+1

si Process.MainWindowHandle == IntPtr.Zero no tiene ventana principal –

0

Usted puede simplemente tratar de atrapar la excepción:

Process process = ... 
try 
{ 
    process.WaitForInputIdle(100); 
} 
catch (InvalidOperationException ex) 
{ 
    // no graphical interface 
} 
+0

Sí, puedo ... por alguna razón, esto me parece feo. La mayoría de las bibliotecas y API decentes suelen ser una forma de determinar si una operación que está por realizar es válida o no. Microsoft generalmente proporciona esto. Si no te importa, esperaré un día, a ver si alguien más tiene alguna idea. – Lunivore

+0

Estoy de acuerdo, es bastante feo usar excepciones como esta –

+0

@Lunivore, @Bear Monkey: Me parece ser una excepción en algún lugar entre una [exasperante excepción y una excepción exógena] (http://blogs.msdn.com /b/ericlippert/archive/2008/09/10/vexing-exceptions.aspx). Para evitar que se produzca la excepción, puede P/invocar la función 'WaitForInputIdle'. –

0

que era pensar lo largo de las líneas de esto, todavía feo, pero trys para evitar excepciones.

Process process = ... 

bool hasUI = false; 

if (!process.HasExited) 
{ 
    try 
    { 
     hasUI = process.MainWindowHandle != IntPtr.Zero; 
    } 
    catch (InvalidOperationException) 
    { 
     if (!process.HasExited) 
      throw; 
    } 
} 

if (!process.HasExited && hasUI) 
{ 

    try 
    { 
     process.WaitForInputIdle(100); 
    } 
    catch (InvalidOperationException) 
    { 
     if (!process.HasExited) 
      throw; 
    } 
} 
0

Así como un cheque MainWindowHandle, se puede enumerar los hilos de proceso y comprobar si alguno de ellos hacen referencia a una ventana visible a través de P/Invoca. Esto parece hacer un buen trabajo atrapando las ventanas que falla el primer control.

private Boolean isProcessWindowed(Process externalProcess) 
{ 
    if (externalProcess.MainWindowHandle != IntPtr.Zero) 
    { 
     return true; 
    } 

    foreach (ProcessThread threadInfo in externalProcess.Threads) 
    { 
     IntPtr[] windows = GetWindowHandlesForThread(threadInfo.Id); 

     if (windows != null) 
     { 
      foreach (IntPtr handle in windows) 
      { 
       if (IsWindowVisible(handle)) 
       { 
        return true; 
       } 
      } 
     } 
    } 

    return false; 
} 

private IntPtr[] GetWindowHandlesForThread(int threadHandle) 
{ 
    results.Clear(); 
    EnumWindows(WindowEnum, threadHandle); 

    return results.ToArray(); 
} 

private delegate int EnumWindowsProc(IntPtr hwnd, int lParam); 

private List<IntPtr> results = new List<IntPtr>(); 

private int WindowEnum(IntPtr hWnd, int lParam) 
{ 
    int processID = 0; 
    int threadID = GetWindowThreadProcessId(hWnd, out processID); 
    if (threadID == lParam) 
    { 
     results.Add(hWnd); 
    } 

    return 1; 
} 

[DllImport("user32.Dll")] 
private static extern int EnumWindows(EnumWindowsProc x, int y); 
[DllImport("user32.dll")] 
public static extern int GetWindowThreadProcessId(IntPtr handle, out int processId); 
[DllImport("user32.dll")] 
static extern bool IsWindowVisible(IntPtr hWnd); 
Cuestiones relacionadas