关闭打开资源管理器窗口而不终止explorer.exe

时间:2018-01-08 13:44:44

标签: c# windows winforms

我尝试过搜索,但没有什么能满足我的要求。

我不希望 explorer.exe被终止或重新启动。 我只想关闭任何打开的资源管理器窗口。

4 个答案:

答案 0 :(得分:3)

以下替代方法使用Shell object的COM API来检索和识别文件资源管理器窗口。它需要添加COM引用:

  • Microsoft Shell控件和自动化
  • Microsoft Internet Controls

Shell.Windows方法返回的对象是IEnumerable。集合中的每个对象都是SHDocVw.InternetExplorer实例。如果Document对象是Shell32.ShellFolderView,则资源管理器是文件资源管理器。

    private static void CloseExplorerWindows()

        {
        Shell32.Shell shell = new Shell32.Shell();

        // ref: Shell.Windows method
        // https://msdn.microsoft.com/en-us/library/windows/desktop/bb774107(v=vs.85).aspx
        System.Collections.IEnumerable windows = shell.Windows() as System.Collections.IEnumerable;
        if (windows != null)
            {
            // ref: ShellWindows object
            // https://msdn.microsoft.com/en-us/library/windows/desktop/bb773974(v=vs.85).aspx
            foreach (SHDocVw.InternetExplorer window in windows)
                {
                object doc = window.Document;
                if (doc != null && doc is Shell32.ShellFolderView)
                    {
                    window.Quit();  // closes the window
                    }
                }
            }
        }

答案 1 :(得分:1)

    public static void CloseExplorerWindows() => EnumWindows(new EnumWindowsProc(EnumTheWindows), IntPtr.Zero);

    private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
    [DllImport("user32.dll", CharSet = CharSet.Unicode)]
    private static extern int GetWindowText(IntPtr hWnd, StringBuilder strText, int maxCount);
    [DllImport("user32.dll", CharSet = CharSet.Unicode)]
    private static extern int GetWindowTextLength(IntPtr hWnd);
    [DllImport("user32.dll")]
    private static extern bool EnumWindows(EnumWindowsProc enumProc, IntPtr lParam);
    [DllImport("user32.dll")]
    private static extern bool IsWindowVisible(IntPtr hWnd);
    [DllImport("user32.dll", SetLastError = true)]
    static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);

    static uint WM_CLOSE = 0x10;

    private static bool EnumTheWindows(IntPtr hWnd, IntPtr lParam)
    {
        int size = GetWindowTextLength(hWnd);
        if (size++ > 0 && IsWindowVisible(hWnd))
        {
            var sb = new StringBuilder(size);
            GetWindowText(hWnd, sb, size);

            var threadID = GetWindowThreadProcessId(hWnd, out var processID);
            var s = System.Diagnostics.Process.GetProcessById((int)processID).ProcessName;

            if (s == "explorer" && sb.ToString() != "Program Manager")
                SendMessage(hWnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
        }
        return true;
    }

答案 2 :(得分:1)

    [DllImport("user32.dll")]
    private static extern bool EnumWindows(EnumWindowsDelegate lpEnumFunc, IntPtr lParam);
    [DllImport("user32.dll")]
    private static extern IntPtr GetWindowThreadProcessId(IntPtr hWnd, out IntPtr lpdwProcessId);
    [DllImport("user32.dll")]
    private static extern uint RealGetWindowClass(IntPtr hwnd, StringBuilder pszType, uint cchType);
    [DllImport("user32.dll")]
    static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);

    static uint WM_CLOSE = 0x10;

    private delegate bool EnumWindowsDelegate(IntPtr hwnd, IntPtr lParam);

    private static bool EnumWindowsCallback(IntPtr hwnd, IntPtr lParam)
    {
        IntPtr pid = new IntPtr();
        GetWindowThreadProcessId(hwnd, out pid);
        var wndProcess = System.Diagnostics.Process.GetProcessById(pid.ToInt32());
        var wndClass = new StringBuilder(255);
        RealGetWindowClass(hwnd, wndClass, 255);
        if (wndProcess.ProcessName == "explorer" && wndClass.ToString() == "CabinetWClass")
        {
            //hello file explorer window...

            SendMessage(hwnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero); // ... bye file explorer window
        }
        return (true);
    }

    static void Main()
    {
        EnumWindowsDelegate childProc = new EnumWindowsDelegate(EnumWindowsCallback);

        EnumWindows(childProc, IntPtr.Zero);

        Console.ReadKey();
    }

编辑:
所以我想唯一有趣的事情就是每个枚举窗口都会被windows调用的回调(hwnd中所说窗口的句柄)

GetWindowThreadProcessId为我们提供了给定窗口句柄的processid

GetProcessById然后为我们提供了一个进程对象,用于从

中读取进程名称等内容

RealGetWindowClass为我们提供了给定窗口句柄的注册类名

最后,我们可以查看当前窗口的进程是否为资源管理器,窗口类是否为" CabinetWClass",这是普通文件资源管理器窗口的窗口类

最后但并非最不重要的是,如果我们的检查没问题,请发送WM_CLOSE消息,请窗口关闭...

答案 3 :(得分:0)

默认情况下,资源管理器作为单个进程运行,任何打开的窗口都只是该进程的一个线程。
通常,要关闭程序,您需要向进程发送一条关闭消息。在这种情况下,关闭explorer.exe将关闭所有资源管理器窗口。

要关闭单个窗口,您需要通过自己的过程打开每个窗口。 这可以通过注册表设置或在“视图”->“选项”->“视图”->“高级设置”下启用:“启动...单独的过程”

a)在您要关闭的窗口中找到PID(进程ID)。

通过taskmanager:
1.在进程列表中,单击“ Windows资源管理器”左侧的箭头
2.检查窗口名称是否与您要关闭的窗口匹配
3.右键单击“ Windows资源管理器”,单击“转到详细信息”
4.记录pid

通过CMD:
tasklist /V /FI "IMAGENAME eq explorer.exe"

如果在自己的进程中打开了每个浏览器窗口,则上述命令将在最后一列显示窗口标题。
否则将显示“ N / A”。

所有资源管理器窗口的pid将相同。 Explorer.exe进程具有自己的pid,标题为“ N / A”
如果已启用“单独过程”,例如通过“文件夹视图”选项,然后可以通过taskkill的进程ID和过滤器选项关闭每个窗口。

要关闭,必须先激活所需的窗口,否则使用pid关闭将关闭最后一个活动窗口,或者使用窗口标题过滤器关闭将给出错误:

信息:没有按指定条件运行的任务。

b)taskkill /pid <pid> 将关闭最后一个活动窗口。
重复此命令将进入下一个窗口。

taskkill /im explorer.exe /fi "windowtitle eq <window name>"
taskkill /fi "IMAGENAME eq explorer.exe" /fi "windowtitle eq <window name>"

<窗口名称>不区分大小写
如果在“文件夹”视图中启用了标题栏中的完整路径,请添加完整路径或通配符。

要关闭所有资源管理器窗口,请执行以下操作:
taskkill /im explorer.exe

注意:

  1. 如果启用了窗口重用,则要激活资源管理器窗口,请发出相同的命令来打开窗口。
  2. 资源管理器窗口的进程的pid在响应表的最后一行中的“ PID”列中;可以通过FOR循环进行访问。
  3. 从@HelpingHand关闭窗口的vbs解决方法:
    https://superuser.com/questions/1263315/how-to-close-a-particular-opened-folder-using-cmd-or-batch-file
  4. 激活窗口的vbs解决方法:
    http://superuser.com/questions/327676/application-to-automatically-switch-between-two-applications-in-windows

在Win 10上测试