【问题标题】:Refresh Windows Explorer in Win7在 Win7 中刷新 Windows 资源管理器
【发布时间】:2011-01-30 03:08:36
【问题描述】:

我的程序设置"HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced""Hidden"。但是,我无法刷新资源管理器以考虑此更改。我试过了:

1)

    SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, IntPtr.Zero, IntPtr.Zero);` 

2)

    SHELLSTATE state = new SHELLSTATE(); 
    state.fShowAllObjects = (uint)1; 
    SHGetSetSettings(ref state, SSF.SSF_SHOWALLOBJECTS, true); 

3)

    SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, SPI_SETNONCLIENTMETRICS, 0, SMTO_ABORTIFHUNG, 5000, ref dwResult); 

4)

    SendMessage(HWND_BROADCAST, WM_COMMAND, 28931 /* Refresh */, 0); 

没有任何作用。所以我该怎么做?如果我自己用 F5 刷新 Explorer,那么它可以工作。但是我想要一些优雅的解决方案,所以它会在任何地方刷新显示,即使在当前打开的OpenFile/SaveFile 对话框中也是如此。

我正在使用 C# .NET,Win7。

状态更新 #1

正如Anders 所指出的,有一种使用 COM 刷新资源管理器窗口的简单方法:

Guid CLSID_ShellApplication = new Guid("13709620-C279-11CE-A49E-444553540000");
Type shellApplicationType = Type.GetTypeFromCLSID(CLSID_ShellApplication, true);
dynamic shellApplication = Activator.CreateInstance(shellApplicationType);
dynamic windows = shellApplication.Windows();
for (int i = 0; i < windows.Count; i++)
    windows.Item(i).Refresh();

所以这部分完成了。 但是我仍然需要刷新OpenFile/SaveFile 对话框,而上面的代码并没有这样做。有人知道如何刷新这些对话框吗?

重要的一点是,如果我在控制面板的文件夹选项中更改“显示隐藏文件”,那些OpenFile/SaveFile 对话框不会被系统刷新,我必须使用 F5 手动刷新它们。我只是在寻找一种如何使用 C# 刷新所有这些对话框的方法,所以我不再需要按 F5...

状态更新 #2

好的,上面代码的新问题 - 它不仅刷新 Windows 资源管理器,还刷新 Internet Explorer...知道如何仅刷新 Windows 资源管理器吗?

【问题讨论】:

  • @SLaks:也许它是一个调整工具?
  • @SLaks:对,因为发帖人有 1 个代表,所以没想过要检查以前的问题。
  • @SLaks:链接中的应用程序与这个不同,我一次开发更多应用程序。这个问题中的应用程序只是一个程序,它注册一个热键(例如 Ctrl+H),它将切换资源管理器“隐藏”设置并刷新资源管理器...
  • 我明白了;听起来很有用。我道歉。不过我没有答案

标签: c# .net windows windows-7 windows-explorer


【解决方案1】:

我想出了一种方法来检查窗口是否是 Windows 资源管理器窗口,并且没有足够的代表来添加评论,所以我想我会提交它作为帮助你的答案,因为这个问题有帮助我出去。

        // based on http://stackoverflow.com/questions/2488727/refresh-windows-explorer-in-win7
        Guid CLSID_ShellApplication = new Guid("13709620-C279-11CE-A49E-444553540000");
        Type shellApplicationType = Type.GetTypeFromCLSID(CLSID_ShellApplication, true);

        object shellApplication = Activator.CreateInstance(shellApplicationType);
        object windows = shellApplicationType.InvokeMember("Windows", System.Reflection.BindingFlags.InvokeMethod, null, shellApplication, new object[] { });

        Type windowsType = windows.GetType();
        object count = windowsType.InvokeMember("Count", System.Reflection.BindingFlags.GetProperty, null, windows, null);
        for (int i = 0; i < (int)count; i++)
        {
            object item = windowsType.InvokeMember("Item", System.Reflection.BindingFlags.InvokeMethod, null, windows, new object[] { i });
            Type itemType = item.GetType();

            // only refresh windows explorers
            string itemName = (string)itemType.InvokeMember("Name", System.Reflection.BindingFlags.GetProperty, null, item, null);
            if (itemName == "Windows Explorer")
            {
                itemType.InvokeMember("Refresh", System.Reflection.BindingFlags.InvokeMethod, null, item, null);
            }
        }

【讨论】:

  • 但是Win7中的Windows资源管理器有些奇怪。如果我在注册表中设置“隐藏”值,而没有运行 Windows 资源管理器,然后启动 Windows 资源管理器,那么他不会考虑注册表更改,我需要在启动后刷新它。幸运的是,您是否知道如何强制 Win Explorer 将更改考虑在内?定期刷新所有 Explorer 以确保所有新启动的 Explorer 都得到刷新不是很好的解决方案。 :-(
  • 起初,代码在 Windows 8 上对我不起作用。我添加了对 itemName == "File Explorer" 的额外检查。 if (itemName == "Windows Explorer" || itemName == "File Explorer") 之后它起作用了。这个post 说它在 Windows 8 中被重命名为文件资源管理器。谢谢。
  • 我偶尔会得到一个空项目。通过在尝试获取项目类型之前简单地检查 null 来修复它,即。 if (item != null ) 类型 itemType = item.GetType();
【解决方案2】:

我不知道“打开/保存”对话框,但您可以通过 COM 自动化获取打开的资源管理器窗口列表,Shell.Application 对象有一个 collection of windows,或者直接 CoCreate IID_IShellWindows,列表中的每个窗口都有刷新方法。

WSH/JScript:

for(var sw=new ActiveXObject("Shell.Application").Windows(),i=0;i<sw.Count; ++i)
   sw.Item(i).Refresh();

我不了解 C#,但这里有处理 WSH/JScriptc++ 中的 shell 窗口的示例

【讨论】:

  • 好吧,我发现只有这种方式:web.archive.org/web/20080205152949/http://… 在 C# 中执行上述代码。我希望我错过了什么,因为那样不太方便......
  • 你可以在C#中调用COM代码(或者把我的代码放在一个.js文件中,用wscript.exe执行)
  • 我应该将 System.Runtime.InteropServices.Marshal.GetActiveObject("Shell.Application"); 返回的对象转换为什么?我只是找不到任何合适的接口(我对 COM 真的不太了解)。
  • 我无法让它运行。我试过这段代码:pastebin.com/GFhPCWwX,但它只是在 GetActiveObject (MK_E_UNAVAILABLE) 上抛出了一个异常。我试过用管理员权限运行程序,同样的例外......我错过了什么?
【解决方案3】:

当您安装注册文件类型的应用程序时,资源管理器窗口经常刷新以指示新关联 - 您能否监视安装程序正在进行的 API 调用以查看它如何刷新窗口?

【讨论】:

  • 我猜它可能会调用 SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, IntPtr.Zero, IntPtr.Zero);,但我猜这不会刷新隐藏文件(没试过)。
  • 现在我想,你可以在打开隐藏文件时钩住窗口。然后你会得到确切的 API 调用......
  • 我已经尝试挂钩 windows 消息,并且看起来系统正在发送 WM_WININICHANGE 消息。但出于某种奇怪的原因,如果我将该消息发送到资源管理器窗口,他们就会忽略它。
  • 可能是完整性级别问题吗?如果您作为低完整性进程运行,那么系统将阻止您的窗口消息到达高完整性进程,我认为...
  • @JonathanGilbert 我无法想象 Paya 仍在努力解决这个问题,因为他们在 6 年前提出了这个问题......
【解决方案4】:

Windows 10 更改了资源管理器窗口的名称:

if ((itemName == "Windows Explorer") || (itemName == "File Explorer")) {
    itemType.InvokeMember("Refresh", System.Reflection.BindingFlags.InvokeMethod, null, item, null);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-03
    相关资源
    最近更新 更多