2013-04-24 14 views
7

questo è il mio codice:C# Process.MainWindowHandle restituisce sempre IntPtr Zero

  using (Process game = Process.Start(new ProcessStartInfo() { 
     FileName="DatabaseCheck.exe", 
     RedirectStandardOutput = true, 
     CreateNoWindow = true, 
     UseShellExecute = false })) 
     { 
      lblLoad.Text = "Loading"; 
      int Switch = 0; 

      while (game.MainWindowHandle == IntPtr.Zero) 
      { 
       Switch++; 
       if (Switch % 1000 == 0) 
       { 
        lblLoad.Text += "."; 
        if (lblLoad.Text.Contains("....")) 
         lblLoad.Text = "Loading."; 

        lblLoad.Update(); 
        game.Refresh(); 
       } 
      } 

Il problema è che è sempre game.MainWindowHandle IntPtr.Zero. Devo trovare l'IntPtr del processo in esecuzione per confermare che il gioco è stato avviato dal programma di avvio, quindi ho fatto in modo che il gioco inviasse il suo IntPtr e che il launcher rispondesse se è ok. Ma per quello, devo conoscere specificamente l'IntPtr del processo di esecuzione.

Grazie in anticipo!

risposta

10

La finestra principale è la finestra aperta dal processo correntemente attivo (il modulo TopLevel). È necessario utilizzare il metodo Refresh per aggiornare l'oggetto Processo su ottenere l'handle della finestra principale corrente se è stato modificato.

È possibile ottenere la proprietà MainWindowHandle solo per i processi in esecuzione sul computer locale. La proprietà MainWindowHandle è un valore che identifica in modo univoco la finestra associata al processo.

A un processo è associata una finestra principale solo se il processo ha un'interfaccia grafica. Se il processo associato non ha una finestra principale, il valore MainWindowHandle è zero. Il valore è anche zero per i processi che sono stati nascosti, cioè i processi che non sono visibili nella barra delle applicazioni. Questo può essere il caso per i processi che appaiono come icone nell'area di notifica, all'estrema destra della barra delle applicazioni.

Se si è appena avviato un processo e si desidera utilizzare l'handle della finestra principale, è consigliabile utilizzare il metodo WaitForInputIdle per consentire il completamento del processo, assicurandosi che l'handle della finestra principale sia stato creato. Altrimenti, verrà generata un'eccezione.

+0

tenterà che quando sono a casa. Grazie – Kfirprods

+0

Grazie, ha funzionato. – Kfirprods

+0

Si noti che su 4.5 questo non è più necessario (anecdotal - il mio codice ha funzionato su 4.5 e fallito quando sono passato a 3.5 finché ho aggiunto '.Refresh()') – Basic

2
while (!proc.HasExited) 
{ 
    proc.Refresh(); 
    if (proc.MainWindowHandle.ToInt32() != 0) 
    { 
     return proc.MainWindowHandle; 
    } 
} 
+1

Ciao, il tuo post è stato contrassegnato come "di bassa qualità", probabilmente perché consiste solo di codice. Potresti migliorare in modo massiccio la tua risposta fornendo una spiegazione su come esattamente e perché questo risponde alla domanda? – Ben

3

Una soluzione è quella di enumerare tutte le finestre di primo livello ed esaminare i loro ID di processo finché non si trova una corrispondenza ...


    [DllImport("user32.dll")] 
    public static extern IntPtr FindWindowEx(IntPtr parentWindow, IntPtr previousChildWindow, string windowClass, string windowTitle); 

    [DllImport("user32.dll")] 
    private static extern IntPtr GetWindowThreadProcessId(IntPtr window, out int process); 

    private IntPtr[] GetProcessWindows(int process) { 
     IntPtr[] apRet = (new IntPtr[256]); 
     int iCount = 0; 
     IntPtr pLast = IntPtr.Zero; 
     do { 
      pLast = FindWindowEx(IntPtr.Zero, pLast, null, null); 
      int iProcess_; 
      GetWindowThreadProcessId(pLast, out iProcess_); 
      if(iProcess_ == process) apRet[iCount++] = pLast; 
     } while(pLast != IntPtr.Zero); 
     System.Array.Resize(ref apRet, iCount); 
     return apRet; 
    }