1

Full repro example (.NET Framework 4.8 Console application, Windows 10):

using System.Diagnostics;
using System.Windows.Forms;

static class Program
{
    static void Main()
    {
        var p = Process.Start("explorer.exe", @"C:\Windows");
        p.WaitForInputIdle();
        // Thread.Sleep(5000);
        MessageBox.Show("Explorer window has opened.");
    }
}

Actual behavior: The message box shows up. A few seconds later, the Explorer window opens in front of the message box, thereby hiding the message.

Desired behavior: The code waits until the Explorer window is visible (that's what I expected WaitForInputIdle to do) and then shows the message box in front of the Explorer window.

What I've already tried:

  • If I activate the Thread.Sleep statement in my code example, it works (i.e., I get the desired behavior). I don't like that solution, because the time it takes to open the Explorer window might be different on my computer and on my customers' computers.
  • I tried various combinations of the various ProcessStartInfo options (UseShellExecute, WindowStyle, CreateNoWindow), but it did not make a difference. Note that I don't want to hide the Explorer window, I just want to wait until it's visible.
  • I know that I can use SetForegroundWindow to make my process the foremost window. That doesn't help. It's (a) apparently not necessary (the Thread-Sleep-variant works without it) and (b) I'd need to do it after the Explorer window finished opening to prevent the Explorer window from "stealing" the foreground again, leading back to my original problem.
  • I also tried checking p.MainWindowTitle in a loop, but that value stays empty even after the window has opened (or the process exits). Apparently, the new Explorer window is actually owned by a different process than the one I started.
  • I know that I could use the Windows API methods FindWindow or EnumWindows to find out if any window with the name of the folder exists, but that's (a) a lot of work and (b) not very elegant.

Did I miss an obvious, correct solution to this?

Heinzi
  • 167,459
  • 57
  • 363
  • 519

2 Answers2

0

You can find a solution to your problem here : https://stackoverflow.com/a/35789386/18486478.

I also find it cleaner to use the Responding variable.

var p = Process.Start("explorer.exe", @"C:\Windows");
while (!p.Responding)
{
    Thread.Sleep(1);
    p.Refresh();
}
p.WaitForInputIdle();
MessageBox.Show("Explorer window has opened.");
Rikube
  • 41
  • 7
  • 1
    Except this doesn't work for the immediately-exiting Explorer.exe. – CodeCaster Mar 08 '23 at 15:08
  • Indeed, I tried using it with another program but the behaviour of exporer.exe is different. I can't access the process after it was started so the best bet is to find how to get the new process created. – Rikube Mar 08 '23 at 15:33
0

I'm afraid you have to use the not very elegant way.

If you try:

var p = Process.Start("explorer.exe", @"C:\Windows");
p.WaitForExit();
MessageBox.Show("Explorer window has opened.");

You will find the message box still shows, this means the window you saw doesn't belong to the process you created. There is a default explorer process when Windows starts, the new explorer process seems to like looking for the default one and let it create a new window. There is an option called "Launch folder windows in a separate process", unfortunately, after my test, this option does not work now.

shingo
  • 18,436
  • 5
  • 23
  • 42