2010-09-24 10 views
9

Utilizzo l'automazione per testare un'applicazione, ma a volte desidero avviare l'applicazione tramite un file batch. Quando eseguo "process.WaitForInputIdle (100)" viene visualizzato un messaggio di errore:Come posso sapere se un processo ha un'interfaccia grafica?

"WaitForInputIdle non riuscito. Ciò potrebbe essere dovuto al fatto che il processo non ha un'interfaccia grafica."

Come faccio a sapere se il processo ha un'interfaccia grafica o no?

risposta

6

Vedi Environment.UserInteractive. Questo identificherà se il processo ha un'interfaccia, ad es. i servizi non sono interattivi all'utente.

Si potrebbe anche guardare Process.MainWindowHandle che vi dirà se c'è un'interfaccia grafica.

Una combinazione di questi due controlli dovrebbe coprire tutte le possibilità.

+0

Purtroppo file batch sembra essere utente interattiva (questo restituisce "vero" sia per il file batch e la finestra). – Lunivore

+0

Quando si dice che Process.MainWindowHandle potrebbe essere usato per fare questo - come? Stai pensando di metterlo in un'altra risposta? – Lunivore

+1

se Process.MainWindowHandle == IntPtr.Zero non ha una finestra principale –

0

Si può semplicemente cercare di catturare l'eccezione:

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

Sì, posso ... per qualche motivo questo mi sembra brutto però. La maggior parte delle librerie e delle API decenti di solito è un modo per determinare se un'operazione che stai per eseguire è valida o meno. Di solito, Microsoft lo fornisce. Se non ti dispiace, aspetterò un giorno, vedere se qualcun altro ha qualche idea. – Lunivore

+0

Sono d'accordo, è piuttosto brutto usare eccezioni come questa –

+0

@Lunivore, @Bear Monkey: Mi sembra un'eccezione da qualche parte tra [un'eccezione vedente e un'eccezione esogena] (http://blogs.msdn.com /b/ericlippert/archive/2008/09/10/vexing-exceptions.aspx). Per evitare l'eccezione dell'eccezione potresti P/Richiamare la funzione 'WaitForInputIdle'. –

0

ero pensare lungo le linee di questo, ancora brutto ma trys per evitare eccezioni.

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

Così come un controllo MainWindowHandle, si possono elencare i fili di processo e verificare se qualcuno di loro riferimento una finestra visibile tramite P/richiama. Questo sembra fare un buon lavoro catturando qualsiasi finestra che manchi al primo controllo.

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);