Dainius Vaičiulis
Dainius Vaičiulis

Reputation: 502

How to close specific file explorer in C#?

It is fairly easy to close a file explorer based on its window name, like this:

msWinHelper Class:

    [DllImport("user32.dll", SetLastError = true)]
    public static extern IntPtr FindWindow(string strClassName, string strWindowName);
    [DllImport("user32.dll", SetLastError = true)]
    public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);

    static uint WM_CLOSE = 0x10;

    public IntPtr findWindow(string className, string name)
    {
        return FindWindow(className, name);
    }

    public void closeWindow(string className, string windowName)
    {
        SendMessage(findWindow(className, windowName), WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
    }

Main program:

msWinHelper.closeWindow(null, "WindowName");

However in some occasions this is not sufficient. Lets say I have two directories with the same subdirectories. If I open a subdir DIR1 from parent folder FOLD1 and another DIR1 from FOLD2, window names become the same. Therefore code cannot determine which is the parent folder and would not necessarily close the one I want.

Is it possible to close an opened folder based on its full path?

Upvotes: 2

Views: 1750

Answers (2)

Alex K.
Alex K.

Reputation: 175768

The shell has an automation interface that allows enumeration of explorer windows.

Add COM references to shell32.dll and shdocvw.dll then you can:

foreach (SHDocVw.InternetExplorer window in new SHDocVw.ShellWindows())
{
    if (Path.GetFileNameWithoutExtension(window.FullName).ToLowerInvariant() == "explorer")
    {
        if (Uri.IsWellFormedUriString(window.LocationURL, UriKind.Absolute))
        {
            string location = new Uri(window.LocationURL).LocalPath;

            if (string.Equals(location, @"C:\close\me", StringComparison.OrdinalIgnoreCase))
                window.Quit();
        }
    }

Upvotes: 4

ErrCode
ErrCode

Reputation: 306

Most likely you'll need to do more than use FindWindow because unfortunately it will always return only one of the Explorer windows (which may not be the one you're looking for).

  1. If you want to persist with FindWindow, one option you could do is change the Explorer setting options so that the full location path is shown in the title of the window (pretty sure from Windows 8 onwards, you can go to the View tab and click on the Options button to the far right to tick the Display the full path in the title bar setting). Explorer -> View tab -> Options
    Once you have this option enabled, then you should be able to supply the folder path to FindWindow for it to search for the matching window since it will have the full folder path in the title (assuming that the title bar with that folder path is unique). You may want to check that it is an Explorer window via GetWindowThreadProcessId to get a process ID and use this PID with System.Diagnostics.Process.GetProcessById and check "explorer" is returned in the property ProcessName

  2. Alternatively you'll have to find the Address: text from the control within the Explorer window itself to work out the exact folder location that the window is showing. Note: You will need to use a different call to find the other window if the address doesn't match the one you're looking for. So maybe something like this:

    • use EnumWindows to enumerate all top-level windows;
    • use GetWindowThreadProcessId with each top-level window handle and with the returned process ID, use System.Diagnostics.Process.GetProcessById and probably ProcessName to check that it is an Explorer window;
    • use EnumChildWindows to enumerate controls within the supplied parent window handle (strange name, but apparently all 'controls' are just 'windows' for winapi);
    • use GetWindowText to examine the text content for the control and check it matches the folder path you're looking for where it has Address: as a prefix;
    • if all the criteria matches, then it should be the window you want to close.

Background on how to find about control details yourself: I usually use AutoIt's Au3Info application to help find such information (also because I usually use AutoIt's scripting language to make a quick prototype for these kind of tasks). Use the 'Finder Tool' by dragging the circular 'aiming' icon over the target Explorer window and address control and release the mouse when you are ready to examine the information for that window/control. Here are some screenshots of what the tool shows when I run it under Windows 10 (details may differ slightly for a different version of Windows). PS: If you're not bound to C# and happy to learn AutoIt's scripting language, you could also try AutoIt for your task.

AutoIt's Au3Info Window <code>Visible Text</code> info AutoIt's Au3Info 'Address' control <code>Control</code> info

References:

Upvotes: 1

Related Questions