【问题标题】:Weird Windows 7 desktop icons cache奇怪的 Windows 7 桌面图标缓存
【发布时间】:2011-08-05 02:58:44
【问题描述】:

我正在编写一个 C# 应用程序来更改桌面上的默认回收站图标。我通过将图标转移到驱动器上的特定位置并更新注册表以指向新图标来做到这一点。这很好用。

但是,问题是当我卸载应用程序并希望将图标设置为默认值时。当我使用 Windows 中的内置功能进行测试时,我注意到 Windows 有时会将注册表更改为 %SystemRoot%\System32\imageres.dll,50 用于空图标,%SystemRoot%\System32\imageres.dll,49 用于完整图标,有时%SystemRoot%\System32\imageres.dll,-55 用于空图标,%SystemRoot%\System32\imageres.dll,-54 用于完整图标。我真的找不到有时使用 50 和 49 有时使用 -55 -54 作为默认回收站图标的逻辑,也找不到有关此问题的任何信息。

我也尝试删除 User\username\AppData\Local 中的图标缓存,但没有任何效果。问题是当我重新设置默认图标(例如使用 50 和 49)时,它不会自动更新。我每次都必须手动刷新才能更改其状态(空/满)。如果我之后转到 Windows 中的内置功能并设置回默认图标,如果我使用 50 和 49,它会更改为 -55 或 -54,然后它就可以工作了。什么?注册表中一定有其他地方触发了这个..你能帮我吗?

我正在使用的注册表中的位置:

HKEY_CURRENT_USER\
Software\
Microsoft\
Windows\
CurrentVersion\
Explorer\
CLSID\
{645FF040-5081-101B-9F08-00AA002F954E}\
DefaultIcon

编辑18/04-2011 在安德斯的帖子之后,我想出了这个:

[System.Runtime.InteropServices.DllImport("User32.dll")]
public static extern int SystemParametersInfo(int uAction, int uParam, string lpvParam, int fuWinIni);
[System.Runtime.InteropServices.DllImport("User32.dll")]
public static extern long SendMessageTimeout(int hWnd, int Msg, int wParam, int lParam, int fuFlags, int uTimeout, out int lpdwResult);

private const int SPI_SETICONS = 0x0058;
private const int SPIF_UPDATEINIFILE = 0x1;
private const int SPIF_SENDWININICHANGE = 0x2;
private const int HWND_BROADCAST = 0xffff;
private const int WM_SETTINGCHANGE = 0x001A;
private const int SMTO_ABORTIFHUNG = 0x0002;
private const int SPI_SETNONCLIENTMETRICS = 0x0002;

        int res = 0;
        RegistryKey iconSizeKey = Registry.CurrentUser.OpenSubKey("Control Panel\\Desktop\\WindowMetrics", true);
        int iconSize = Int16.Parse((string)iconSizeKey.GetValue("Shell Icon Size"));
        int newIconSize = iconSize - 1;
        iconSizeKey.SetValue("Shell Icon Size", newIconSize, RegistryValueKind.String);
        SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, SPI_SETNONCLIENTMETRICS, 0, SMTO_ABORTIFHUNG, 100000, out res);
        iconSizeKey.SetValue("Shell Icon Size", iconSize, RegistryValueKind.String);
        SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, SPI_SETNONCLIENTMETRICS, 0, SMTO_ABORTIFHUNG, 100000, out res);

但这并没有改变任何东西:(

编辑19/02-2011 在安德斯的帖子之后我更新了这个:

[System.Runtime.InteropServices.DllImport("Shell32.dll")]
private static extern int SHChangeNotify(int eventId, int flags, IntPtr item1, IntPtr item2);

并尝试了所有这些组合:

    SHChangeNotify(0x8000000, 0x1000, IntPtr.Zero, IntPtr.Zero);
    SHChangeNotify(0x08000000, 0x1000, IntPtr.Zero, IntPtr.Zero);
    SHChangeNotify(0x00008000, 0x1000, IntPtr.Zero, IntPtr.Zero);
    SHChangeNotify(0x00002000, 0x1000, IntPtr.Zero, IntPtr.Zero);

还是不行:(

【问题讨论】:

  • 我无法想象是什么让你选择这样做。用户拥有桌面并拥有大量进行更改的工具。您依赖注册表中的实现细节不会打扰您吗?
  • 它确实困扰着我。但是有什么选择呢?我真的没有看到提供更改图标(使用内置 win 方法)作为选项的指南。
  • @s0mmer 为什么需要这样做?为什么您的用户会接受您以这种方式弄乱他们的系统。如果我在我的机器上安装了执行此操作的软件,我会非常生气并会快速卸载它。
  • @David Heffernan:我想简化在用户计算机上安装特定图标的过程。用户将获得有关过程的通知,并且必须在应用程序执行任何操作之前接受这一点。
  • @s0mmer 为什么用户希望他们的回收站图标改变?这是什么类型的应用程序?

标签: c# windows windows-7


【解决方案1】:

-55 是资源 id,50 是资源 index。资源 id 由开发人员设置,索引是从 0 开始的计数(计数可以在服务包等中更改,但它们通常非常稳定)。您可以使用Resource Hacker 之类的工具查看资源 ID(在图标组中查找图标 ID)

当您在图标选择器对话框中选择图标时,通常会使用索引。我希望特定的 Windows 重置按钮可以使用资源 ID...

请参阅this answer 了解强制刷新 shell 图标的方法

【讨论】:

  • 感谢您的回复。我将尝试使用 id,并在我下班回家时强制刷新 shell 图标。我会回复你的。
  • 我很难将代码转换为 C# - 你能帮帮我吗?
  • 我已完成代码转换 - 请查看我的编辑。我做错了吗?
  • @s0mmer:我觉得没问题,也许你可以尝试在第二次发布消息之前添加一点睡眠。或者您可以改变策略并尝试使用 SHCNE_ASSOCCHANGED 或 SHCNE_UPDATEIMAGE 或 SHCNE_UPDATEITEM 的 SHChangeNotify ...
  • @Anders:我回家后会试试这个。我会回复你的。
猜你喜欢
  • 2019-10-16
  • 1970-01-01
  • 2011-03-29
  • 1970-01-01
  • 1970-01-01
  • 2017-05-24
  • 2011-05-22
  • 2011-01-27
  • 1970-01-01
相关资源
最近更新 更多