1

I have a strange behaviour when I try to start explorer.exe from c# like this:

ProcessStartInfo info = new ProcessStartInfo("explorer.exe", "E:");
info.WindowStyle = ProcessWindowStyle.Hidden;
Process process = new Process();
process.StartInfo = info;
process.Start();
Thread.Sleep(2000);
bool res = process.CloseMainWindow(); // InvalidOperationException -> already exited
process.Close();
process.WaitForExit(5000);

The problem is:

the exception seems correct, because at this point HasExited returns already true. Nevertheless in the taskmanager the created instance of explorer is still present.

So I dont understand what my call does. I had thought it would directly start an instance of explorer, but it seems not or the explorer works in some different way.

And my second question: how can I start and shortly after that stop a new specific instance of explorer programmatically?

Edit to answer some questions:

  • explorer option Launch Folder Windows in a separate process is set to true
  • the created process.Id is not present in taskmanager. For example: the new explorer instance shown in taskmanager has PID 4968 while the debugger shows 10752 as ID of the created (and exited) process.

Edit: here a screenshot from taskmanager after ~12 debug runs enter image description here

casiosmu
  • 797
  • 1
  • 8
  • 22
  • 1
    `the created instance of explorer is still present.` Are you **sure** it is the `created instance` of explorer, or just the default one that is always running? – mjwills Nov 30 '17 at 13:25
  • `process.Close(); process.WaitForExit(5000);` why is the process.Close() there – MethodMan Nov 30 '17 at 13:25
  • @mjwills yes, I'm sure, it is the created instance. – casiosmu Nov 30 '17 at 13:30
  • @MethodMan thats from an MSDN example – casiosmu Nov 30 '17 at 13:30
  • So there are two running explorer.exe processes? Could you show us a screenshot of that in Task Manager? – mjwills Nov 30 '17 at 13:31
  • @mjwills In fact, with every debug run I created an additional instance so for now I have 13 explorer instances in taskmanager – casiosmu Nov 30 '17 at 13:33
  • 3
    Don't be mislead by Task Manager, Explorer creates a process for every tab in its main window. Explorer is a single-instance process. If you start it again then it will simply ask the 1st instance to display the URL. And quits. Feature, not a bug. Use the IShellWindows interface to find running instances back. – Hans Passant Nov 30 '17 at 13:35
  • *"the explorer works in some different way"* - this. What are you trying to achieve? – Sinatr Nov 30 '17 at 13:40

2 Answers2

2

This may be down to the fact that the explorer.exe process in question HAS exited. Windows does some strange things with multiple explorer windows and it depends on the options you have set. By default, all windows end up running in a single process if I remember correctly.

What I would do is output the processid for the process you just generated:

Console.WriteLine($"{process.Id} has exited {process.HasExited}");

Then look at task manager to see if you can find the corresponding process. I would imagine that the HasExited is true so you won't find the process, but the window will have opened.

You may have to set process.EnableRaisingEvents to true to get a valid answer from process.HasExited, I can't recall of the top of my head.

Also check the setting in Explorer via Folder Options to see if you have Launch Folder Windows in a separate process enabled or not on the view tab.

IF you do find your process, you can always kill off that process and see if your windows closes. If it does, then it may be that the explorer.exe is not creating a main window handle which you can check using Spy++


Edited with more info

Further more, @Hans Passant mentioned above that shell windows work different. So what actually happens is this, explorer.exe (1234) contacts the root explorer.exe (321), which in turn then creates a new window (if Launch separate is false) or spawns a subprocess explorer.exe (3445). Your process explorer.exe (1234) having done its job, then exits. No window is ever created by your process so CloseMainWindow() will not find a window to close and errors.

How to close a specific explorer window

To do so you need to utilise ShellWindows, see Is there a way to close a particular instance of explorer with C#?

For reference the code used there was:

ShellWindows _shellWindows = new SHDocVw.ShellWindows();
string processType;

foreach (InternetExplorer ie in _shellWindows)
{
    //this parses the name of the process
    processType = Path.GetFileNameWithoutExtension(ie.FullName).ToLower();

    //this could also be used for IE windows with processType of "iexplore"
    if (processType.Equals("explorer") && ie.LocationURL.Contains(@"C:/Users/Bob"))
        {
            ie.Quit();
        }    
}

Note, you need to be careful that you aren't closing a window the user wanted open in the first place. Is there a reason to close the window?

netniV
  • 2,328
  • 1
  • 15
  • 24
  • 1
    see my edit: the created task doesnt show up in taskmanager, but a new explorer instance with different PID – casiosmu Nov 30 '17 at 13:50
  • Then I think it is as @Hans Passant suggested in his comment above. Your process is spawning, contacting the root explorer.exe process, which in turn is then creating a subprocess of its own. – netniV Nov 30 '17 at 13:52
  • Ok, thanks. Any suggestions how to get the PID of the subprocess so I can close it? – casiosmu Nov 30 '17 at 13:54
  • I've updated my answer to provide some reference for you. – netniV Nov 30 '17 at 14:02
  • Thats working for me, much thanks :-) Yes, I take care. I want to close it to tidy up behind me. I only need explorer to once open the specific path (a disconnected network drive) and then for nothing more. Thats also the reason I create it as hidden so the user never sees it. – casiosmu Nov 30 '17 at 14:21
0

The problem is in the notion of has UI Interface, As per definition:

Closes a process that has a user interface by sending a close message to its main window.

However explorer.exe is far more complicated than a simple process with UI. If for example you use another, application, more simple (e.g Notepad), no exception will be raised:

 ProcessStartInfo info = new ProcessStartInfo("notepad.exe");
            info.WindowStyle = ProcessWindowStyle.Maximized;
            Process process = new Process();
            process.StartInfo = info;
            process.Start();
            Thread.Sleep(2000);
            bool res = process.CloseMainWindow(); // InvalidOperationException -> already exited
            process.Close();
apomene
  • 14,282
  • 9
  • 46
  • 72