我的程序设置
"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 刷新资源管理器,那么它就可以了。不过,我想要一些优雅的解决方案,这样它就会刷新各处的显示,即使是在当前打开的
OpenFile
/SaveFile
对话框中。
我使用的是C# .NET,Win7。
正如
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...
好的,上面的代码出现了新问题 - 它不仅刷新 Windows 资源管理器,还刷新 Internet 资源管理器...知道如何仅刷新 Windows 资源管理器吗?
我找到了一种方法来检查窗口是否是 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);
}
}
我不知道“打开/保存”对话框,但您可以使用 COM 自动化获取打开的资源管理器窗口的列表,Shell.Application对象有一个窗口集合,或者直接 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/JScript 和 c++
中处理 shell 窗口的示例Windows 10 更改了资源管理器窗口的名称:
if ((itemName == "Windows Explorer") || (itemName == "File Explorer")) {
itemType.InvokeMember("Refresh", System.Reflection.BindingFlags.InvokeMethod, null, item, null);
}
当您安装注册文件类型的应用程序时,资源管理器窗口经常刷新以指示新的关联 - 您能否监视安装程序正在进行的 API 调用以查看它如何刷新窗口?
添加@Adam答案https://stackoverflow.com/a/2863647/5514131,“Windows资源管理器”和“文件资源管理器”在非英语Windows版本上不起作用,我们需要获取本地化名称通过读取 explorer.exe MUI 资源文件来打开资源管理器窗口。
SHLoadIndirectString
API 从 explorer.exe.mui 文件中读取文本资源。
[DllImport("shlwapi.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
public static extern int SHLoadIndirectString(string pszSource, StringBuilder pszOutBuf, int cchOutBuf, IntPtr ppvReserved);
static void Main(string[] args)
{
var resourcePath = @"@%SystemRoot%\en-US\explorer.exe.mui,-6020"; //en-US should be replaced with the current Windows language code
resourcePath = Environment.ExpandEnvironmentVariables(resourcePath);
StringBuilder outBuff = new StringBuilder(1024);
var result = SHLoadIndirectString(resourcePath, outBuff, outBuff.Capacity, IntPtr.Zero);
if (result == 0)
{
Console.WriteLine(outBuff.ToString());
}
else
{
Console.WriteLine("SHLoadIndirectString method failed, error code: {0}", result);
}
Console.ReadLine();
}
在 Windows 10 上,这将输出:
File Explorer
@Adam 的解决方案效果很好,谢谢。 但是,我们失去了资源管理器中的选择。有没有办法让我的文件夹在刷新后保持选中状态?