22

Kind of a special case problem:

  • I start a process with System.Diagnostics.Process.Start(..)
  • The process opens a splash screen -- this splash screen becomes the main window.
  • The splash screen closes and the 'real' UI is shown. The main window (splash screen) is now invalid.
  • I still have the Process object, and I can query its handle, module, etc. But the main window handle is now invalid.

I need to get the process's UI (or UI handle) at this point. Assume I cannot change the behavior of the process to make this any easier (or saner).

I have looked around online but I'll admit I didn't look for more than an hour. Seemed like it should be somewhat trivial :-(

Rudi Visser
  • 21,350
  • 5
  • 71
  • 97
shea241
  • 496
  • 1
  • 3
  • 8

9 Answers9

10

If you don't mind using the Windows API, you could use EnumWindowsProc, and check each of the handles that that turns up using GetWindowThreadProcessId (to see that it's in your process), and then maybe IsWindowVisible, GetWindowCaption and GetWindowTextLength to determine which hWnd in your process is the one you want.

Though if you haven't used those functions before that approach will be a real pain, so hopefully there's a simpler way.

JohnB
  • 18,046
  • 16
  • 98
  • 110
MB.
  • 7,365
  • 6
  • 42
  • 42
  • I have found that this is a much more robust solution than FindWindowEx, even though it is harder to set up. FindWindowEx will struggle when you have multiple instances of the target application running. – Zooba Jan 09 '09 at 21:43
7

@ageektrapped is on the right track, however FindWindow will not search child windows.

For that you will need to use FindWindowEx

Rudi Visser
  • 21,350
  • 5
  • 71
  • 97
Ash
  • 60,973
  • 31
  • 151
  • 169
3

Thank you for your answers. Thanks to you here, I figured out how to know if the main window of a process is in front or not:

N.B : of course this needs System.Diagnostic and 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());
}
Cosmin
  • 21,216
  • 5
  • 45
  • 60
Giova
  • 31
  • 1
2

You may find that if you call .Refresh() that you get the new top-level window.

GregUzelac
  • 462
  • 2
  • 6
1

Use Process.GetProcessById(proc.Id); where proc was your splash screen. Works for me.

Now, how do you get to main window properties in System.Windows.Forms to give it focus w/o using win32? After all .net is supposed to be a one-stop solution - is it not?

1

If you know the window's title, you can use the Win32 call, FindWindow, through P/Invoke.

You can find the signature here on pinvoke.net

ageektrapped
  • 14,482
  • 7
  • 57
  • 72
1

From what I understand MainWindowHandle property of the process you are starting is not valid. If that's the case, you can use FindWindow function (from Win32 SDK) which returns the window handle you need. All you need is the class name of target application's main window. You can obtain it using Spy++ or Winspector. You also need to ensure you have the right window by checking that window's process id using GetWindowThreadProcessId.

At last, I have to say I am not an expert on Win32 and there might be a better solution for your case.

blackwing
  • 3,154
  • 3
  • 23
  • 20
0

Somewhere in the code, the "real" main window is created. You can just save the window handle at that time and then after the splash screen closes you can set Application.MainWindow to the real window.

Marcus Erickson
  • 1,561
  • 1
  • 11
  • 10
0

The MainWindowHandle property is cached after it is first accessed which is why you don't see it changing even after the handle becomes invalid. GregUzelac's information is correct. Calling Proces.Refresh will causes the next call to Process.MainWindowHandle to re-do the logic to find a new main window handle. Michael's logic also works because the new Process doesn't have a cached version of the MainWindowHandle.

Matt Ellis
  • 1,051
  • 1
  • 9
  • 8