如何在C#中关闭特定的文件资源管理器?

时间:2017-03-22 08:22:58

标签: c# winapi

根据窗口名称关闭文件浏览器相当容易,如下所示:

msWinHelper课程:

    [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);
    }

主程序:

msWinHelper.closeWindow(null, "WindowName");

然而,在某些情况下,这还不够。假设我有两个具有相同子目录的目录。如果我从父文件夹DIR1打开子目录FOLD1而从DIR1打开另一个FOLD2,则窗口名称将变为相同。因此代码无法确定哪个是父文件夹,也不一定会关闭我想要的文件夹。

是否可以根据其完整路径关闭已打开的文件夹?

2 个答案:

答案 0 :(得分:3)

shell有一个自动化界面,允许枚举资源管理器窗口。

添加对shell32.dll和shdocvw.dll的COM引用,然后您可以:

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();
        }
    }

答案 1 :(得分:1)

您很可能需要做的不仅仅是使用FindWindow,因为很遗憾,它总是只返回一个资源管理器窗口(可能不是您正在寻找的窗口)。 / p>

  1. 如果您希望保留FindWindow,您可以执行的一个选项是更改资源管理器设置选项,以便在窗口标题中显示完整的位置路径(从Windows 8开始,非常确定,您可以转到View标签,然后点击最右侧的Options按钮勾选Display the full path in the title bar设置。 Explorer -> View tab -> Options
    一旦启用此选项,您应该能够提供FindWindow的文件夹路径,以便搜索匹配的窗口,因为它将具有完整的文件夹路径title(假设具有该文件夹路径的标题栏是唯一的)。您可能需要通过GetWindowThreadProcessId检查它是一个资源管理器窗口,以获取进程ID并将此PID与System.Diagnostics.Process.GetProcessById一起使用,并检查"资源管理器"在财产ProcessName

  2. 中返回
  3. 或者,您必须在资源管理器窗口中找到控件中的Address:文本,以确定窗口显示的确切文件夹位置。 注意:如果地址与您正在寻找的地址不匹配,则需要使用其他来电查找其他窗口。也许是这样的:

    • 使用EnumWindows枚举所有顶级窗口;
    • 对每个顶级窗口句柄使用GetWindowThreadProcessId并使用返回的进程ID,使用System.Diagnostics.Process.GetProcessByIdProcessName来检查它是否为资源管理器窗口;
    • 使用EnumChildWindows枚举所提供的父窗口句柄中的控件(奇怪的名称,但显然所有'控件'只是' windows' for winapi) ;
    • 使用GetWindowText检查控件的文本内容,并检查它是否与您在Address:作为前缀查找的文件夹路径相匹配;
    • 如果所有条件都匹配,则它应该是您要关闭的窗口。
  4. 有关如何自行查找控件详细信息的背景信息:我通常使用AutoItAu3Info应用程序来帮助查找此类信息(也因为我通常使用AutoIt的脚本语言为这类任务制作快速原型)。使用' Finder工具'通过拖动圆形'瞄准'目标资源管理器窗口上的图标和地址控制,并在准备检查该窗口/控件的信息时释放鼠标。以下是该工具在Windows 10下运行时显示的屏幕截图(不同版本的Windows的详细信息可能略有不同)。 PS:如果您没有使用C#并且乐于学习AutoIt的脚本语言,您也可以尝试使用AutoIt来完成任务。

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

    参考文献:

相关问题