2011-01-18 7 views
9

Ho una situazione in cui sto avviando un processo nel mio codice per configurare un canale IPC. Il processo che sto avviando è un'applicazione MFC senza supporto CLR. L'applicazione da cui sto avviando questo processo è un modulo C# in un'applicazione WPF (ho pensato che non ritengo che ciò sia consequenziale al mio problema). Questo funziona con una versione dell'applicazione che fa il supporto CLR, e funziona su tutti i computer, tranne la destinazione di distribuzione, un computer touch screen con Windows 7. Ma per qualche ragione, quando provo con questo scenario esatto, l'oggetto processo senza risolve un handle della finestra principale (Process.MainWindowHandle). Esiste un altro metodo (forse persino in voga) per farlo? È una cosa di sicurezza? Sono quello che sta guardando il processo. La maniglia della finestra principale del processo esiste. Non vedo cosa potrebbe essere sbagliato.Perché non è possibile ottenere l'handle della finestra principale per un processo avviato?

Se aiuta, ecco il mio codice.

 _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. 
     } 

Il ApplicationException viene colpito dopo un minuto di cercare di ottenere una maniglia finestra principale diverso da zero.

+1

Sei stanco di usare 'WaitForInputIdle' come suggerito dai documenti MSDN? Inoltre è buona norma usare 'throw' invece di' buttare ex', come si perderanno pila informazioni di traccia con 'ex' tiro (tiro' ex' riavvia il tiro eccezione e quindi traccia dello stack). –

+0

Controllare le modifiche. :) – Jordan

+0

@jordan Vedo la tua modifica. Devi includere @username nei tuoi commenti in modo che l'altro utente a cui stai rispondendo sia avvisato. –

risposta

6

Il valore che si ottiene fuori Process.MainWindowHandle è purtroppo una supposizione. Non è disponibile alcuna funzione API per un programma che consenta di dire a Windows "questa è la mia finestra principale". La regola che usa è documentata, è la prima finestra che viene creata da un processo quando viene avviato. Questo causa problemi se quella prima finestra è, ad esempio, una finestra di accesso o una schermata iniziale.

Non si può fare molto su questo, è necessario sapere di più su come si comporta il programma per trovare la finestra principale reale. Enumerare le finestre con EnumThreadWindows() potrebbe aiutarti a trovarlo, purché la prima finestra sia stata creata sullo stesso thread della finestra principale. Sarà necessario un EnumWindows() più elaborato() se questo non è il caso.

3

L'abitudine è chiamare EnumWindows in un ciclo combinato con GetWindowThreadProcessId per trovare l'handle della finestra.

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

Come mi aiuta esattamente? Sto cercando di ottenere un handle di finestra da un altro processo. Puoi fornirmi un codice? – Jordan

+0

Quindi sostanzialmente questo ottiene tutte le finestre per l'ID di processo specificato, interessante. – Jordan

1

Non so il motivo per cui potrebbe essere diverso, ma dopo aver creato il processo, prova a fare:

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

e vedere se uno dei processi restituiti hanno un MainWindowHandle.

+0

È diverso, ma nel modo opposto. Afferrando un processo in questo modo, non si ha piena fiducia e quindi non si può fare molto di tutto con esso, e certamente non ha la sua maniglia. Solo quando inizi un processo puoi interagire con esso in qualsiasi senso significativo. – Jordan

2

Al fine di ottenere MainWindowHandle mediante il processo, si prega di assicurarsi che l'applicazione WPF viene visualizzata sulla barra delle applicazioni cioè ShowInTaskbar="True" e impostare Application.Current.MainWindow proprietà per la finestra che si desidera impostare come finestra principale.

Se eseguo il codice riportato di seguito nella finestra principale di WPF senza impostare ShowInTaskbar="True", ho sempre ottenuto 0 come MainWindowHandle perché la finestra WPF era a schermo intero e non visualizzata sulla barra delle applicazioni.

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

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