我做了很多图标设计。当我修改 Windows 图标并覆盖原始图标时,资源管理器不会刷新并显示新图标。
如果我更改新图标的名称以使其具有唯一性,我所做的更改将正确显示。但是,如果它与原始未修改的图标同名,它仍然显示旧图标。看来Win10是按名称缓存图标的。
如何使用 Pwsh 强制 Windows 10 的 explorer.exe 刷新其图标缓存?
我发现这篇文章是关于同样的事情,但代码是用 C 语言编写的,我不理解或不熟练:
有没有简单的方法可以从 Powershell 中调用
SHChangeNotify
SHUpdateImage
或 WM_SETTINGCHANGE
?
我可以使用一个 C# 程序集来定义一个帮助程序类来通知 Windows 它需要刷新其缓存吗?
到目前为止我尝试过的:
function Request-WindowsExplorerRefresh {
param (
[switch] $SendF5,
[Int32] $SendF5Delay=150
)
$shellApplication = New-Object -ComObject Shell.Application
$windows = $shellApplication.Windows()
$count = $windows.Count()
foreach( $i in 0..($count-1) ) {
$item = $windows.Item( $i )
if( $item.Name() -like '*Explorer*' ) {
$item.Refresh()
}
}
if($SendF5){
$wshell = New-Object -ComObject wscript.shell;
Start-Sleep -Milliseconds $SendF5Delay
$wshell.SendKeys("{F5}")
Start-Sleep -Milliseconds $SendF5Delay
$wshell.SendKeys("{F5}")
}
}
上面的代码使用 Com 和 Shell.Application 告诉资源管理器刷新。我还有一个可选开关,可以额外按 F5 几次来刷新窗口。不幸的是,这个功能不起作用,并且实际上并没有刷新图标缓存。
我也尝试过这种方法,利用 C# 辅助类:
function Request-WindowsExplorerRefreshAlt {
param ()
$code = @"
using System;
namespace VSYS
{
public static class Util
{
public static void RefreshExplorer(){
Console.WriteLine("Refreshing Explorer");
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 });
if (item != null) {
Type itemType = item.GetType();
// only refresh windows explorer
string itemName = (string)itemType.InvokeMember("Name", System.Reflection.BindingFlags.GetProperty, null, item, null);
if ((itemName == "Windows Explorer") || (itemName == "File Explorer")) {
itemType.InvokeMember("Refresh", System.Reflection.BindingFlags.InvokeMethod, null, item, null);
}
}
}
}
}
}
"@
Add-Type -TypeDefinition $code -Language CSharp
Invoke-Expression "[VSYS.Util]::RefreshExplorer()"
}
此代码也不起作用。所以我现在正在旋转我的轮子,找不到任何解决方案。我认为关键与调用
SHChangeNotify
SHUpdateImage
或广播WM_SETTINGCHANGE
有关。但我完全不知道如何在 Powershell(或 C#)中执行此操作
我确实需要一些帮助,因为当前的 Windows 行为让我陷入困境。
非常感谢任何帮助。
要让 Windows 资源管理器知道某些内容已更改,您需要强制刷新。
根据您的情况,您可以尝试简单地重新启动资源管理器进程:
Stop-Process -ProcessName explorer
另一种方法可以使用 Win32 API,如下所示:
function Refresh-Explorer {
$code = @'
private static readonly IntPtr HWND_BROADCAST = new IntPtr(0xffff); // http://www.pinvoke.net/default.aspx/Constants/HWND.html
private const uint WM_SETTINGCHANGE = (uint)0x1a; // http://www.pinvoke.net/default.aspx/Constants/WM.html
private const uint SMTO_ABORTIFHUNG = (uint)0x0002; // http://www.pinvoke.net/default.aspx/Enums/SendMessageTimeoutFlags.html
private const uint SHCNE_ASSOCCHANGED = (uint)0x08000000L; // http://www.pinvoke.net/default.aspx/Enums/SHChangeNotifyEventID.html
private const uint SHCNF_FLUSH = (uint)0x1000; // http://www.pinvoke.net/default.aspx/Enums/SHChangeNotifyFlags.html
[System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr SendMessageTimeout (IntPtr hWnd, uint Msg, IntPtr wParam, string lParam, uint fuFlags, uint uTimeout, IntPtr lpdwResult);
[System.Runtime.InteropServices.DllImport("Shell32.dll")]
private static extern int SHChangeNotify(uint eventId, uint flags, IntPtr item1, IntPtr item2);
public static void Refresh() {
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_FLUSH, IntPtr.Zero, IntPtr.Zero);
SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, IntPtr.Zero, null, SMTO_ABORTIFHUNG, 100, IntPtr.Zero);
}
'@
Add-Type -MemberDefinition $code -Namespace Win32Refresh -Name Explorer
[Win32Refresh.Explorer]::Refresh()
}
# call the above function to tell explorer something has changed
Refresh-Explorer