.NET (C #): Obtenir des fenêtres enfants lorsque vous n’avez qu’un handle de processus ou un PID?

Genre d’un problème de cas particulier:

  • Je commence un processus avec System.Diagnostics.Process.Start(..)
  • Le processus ouvre un écran de démarrage – cet écran de démarrage devient la fenêtre principale.
  • L’écran de démarrage se ferme et l’interface utilisateur réelle est affichée. La fenêtre principale (écran de démarrage) est maintenant invalide.
  • J’ai toujours l’object Process, et je peux interroger son handle, son module, etc. Mais le handle de la fenêtre principale n’est plus valide.

Je dois obtenir l’interface utilisateur du processus (ou le descripteur d’interface utilisateur) à ce stade. Supposons que je ne puisse pas changer le comportement du processus pour le rendre plus facile (ou plus sain).

J’ai regardé en ligne mais j’avoue que je n’ai pas cherché plus d’une heure. On dirait que ça devrait être quelque peu banal 🙁

Si cela ne vous dérange pas d’utiliser l’API Windows, vous pouvez utiliser EnumWindowsProc et vérifier chacun des GetWindowThreadProcessId utilisent GetWindowThreadProcessId (pour voir qu’il est dans votre processus), puis peut-être IsWindowVisible , GetWindowCaption et GetWindowTextLength dans votre processus est celui que vous voulez.

Bien que si vous n’avez pas utilisé ces fonctions avant que cette approche ne soit un problème, alors nous espérons qu’il ya un moyen plus simple.

@ageektrapped est sur la bonne voie, mais FindWindow ne cherchera pas les fenêtres enfants.

Pour cela, vous devrez utiliser FindWindowEx

Merci pour vos réponses. Grâce à vous ici, j’ai compris comment savoir si la fenêtre principale d’un processus est devant ou non:

NB: bien sûr, cela nécessite System.Diagnostic et System.Runtime.Interrop

 public bool IsWindowActive(Int32 PID) { return IsWindowActive(Process.GetProcessById(PID)); } [DllImport("user32.dll")] private static extern IntPtr GetForegroundWindow(); public bool IsWindowActive(Process proc) { proc.Refresh(); return proc.MainWindowHandle.Equals(GetForegroundWindow()); } 

Vous pouvez trouver cela si vous appelez .Refresh () que vous obtenez la nouvelle fenêtre de niveau supérieur.

Si vous connaissez le titre de la fenêtre, vous pouvez utiliser l’appel Win32, FindWindow, via P / Invoke.

Vous pouvez trouver la signature ici sur pinvoke.net

D’après ce que je comprends, la propriété MainWindowHandle du processus que vous démarrez n’est pas valide. Si tel est le cas, vous pouvez utiliser la fonction FindWindow (à partir de Win32 SDK) qui renvoie le handle de fenêtre dont vous avez besoin. Tout ce dont vous avez besoin est le nom de classe de la fenêtre principale de l’application cible. Vous pouvez l’obtenir en utilisant Spy ++ ou Winspector . Vous devez également vous assurer que vous avez la bonne fenêtre en vérifiant l’ID de processus de cette fenêtre à l’aide de GetWindowThreadProcessId .

Enfin, je dois dire que je ne suis pas un expert de Win32 et qu’il pourrait y avoir une meilleure solution pour votre cas.

Utilisez Process.GetProcessById (proc.Id); où proc était votre écran de démarrage. Travaille pour moi.

Maintenant, comment obtenez-vous les propriétés de la fenêtre principale dans System.Windows.Forms pour lui donner le focus sans utiliser win32? Après tout, .net est censé être une solution unique – n’est-ce pas?

Quelque part dans le code, la fenêtre principale “réelle” est créée. Vous pouvez simplement enregistrer le handle de fenêtre à ce moment-là, puis après la fermeture de l’écran de démarrage, vous pouvez définir Application.MainWindow sur la fenêtre réelle.

La propriété MainWindowHandle est mise en cache après son premier access. C’est pourquoi vous ne la voyez pas changer même après que le descripteur n’est plus valide. Les informations de GregUzelac sont correctes. L’appel de Proces.Refresh provoque l’appel suivant à Process.MainWindowHandle pour refaire la logique pour trouver un nouveau handle de fenêtre principale. La logique de Michael fonctionne également parce que le nouveau processus n’a pas de version mise en cache de MainWindowHandle.