【技术分享】强制刷新文件夹属性(desktop.ini)缓存的方法展示

经验创意 · 1677 次浏览
白云朔 创建于 2024-12-01 22:55

由于Windows文件夹属性的缓存机制,通过脚本修改desktop.ini文件后,desktop.ini中的属性并不会立马生效,普通F5刷新也不会起到任何作用,经过大量网络检索后,终于找到解决方法,并运用到本动作。

现公开我寻找到的解决方法,以便各位搞开发的朋友使用,需要强制刷新文件夹属性缓存的朋友,可以直接看这,免去下载动作慢慢研究浪费的时间。

常规方法:

  1. 等待3~5分钟后,文件资源管理器自动刷新文件夹属性缓存:
    非常好的方法(狗头)

  2. 重启explorer.exe进程(文件资源管理器):
    该方法会造成部分程序和进程中断,影响范围过大。

  3. 更改“日期与设置”(ms-settings:dateandtime)中更改系统时间:
    还是一样的问题,会造成部分程序和进程出现错误(比如搜狗输入法),影响范围过大。

  4. 进入文件夹的属性窗口,在“自定义”选项卡中点击确定(无需更改设置,直接点击确定即可):
    影响范围小,但是太麻烦,唤醒文件夹的属性窗口只能通过模拟键盘操作或PowerShell(并且该方法还会导致PowerShell占用并锁定文件夹)
    Start-Process powershell -ArgumentList "-NoExit", "-Command", "(New-Object -ComObject Shell.Application).Namespace('要打开属性窗口的路径').Self.InvokeVerb('Properties')"

完美解决方法(来自于onlyclxy 大佬)

核心代码(VBS):

set shell = CreateObject("Shell.Application")
set folder = shell.NameSpace("文件夹路径")
folder.MoveHere "desktop.ini文件路径", 4+16+1024

其中,"文件夹路径"是你要刷新的目标文件夹的路径,"desktop.ini文件路径"是你要移动的desktop.ini文件的路径。
该代码能够强制刷新文件夹属性缓存,核心就是通过VBS脚本移动desktop.ini文件,将外部desktop.ini移入,或内部desktop.ini移出再移入,然后执行一次普通的刷新(F5),就能看到文件夹的图标成功被刷新。

你可以在外部(系统Temp文件夹)创建desktop.ini文件,再移入目标文件夹或目标文件夹的父级文件夹就行了。
个人这边建议移入父级文件夹的desktop.ini,因为这可以实现在目标文件夹不止一个,需要批量更新文件夹图标时,只通过该VBS代码执行一次命令,即可刷新父级文件夹中的所有文件夹。
但该方法也有一些小问题,在文件夹视图非详细信息视图时,可能会出现图标不刷新的情况,经过测试,该问题只需要在文件夹中创建任意文件即可。

也就是说,你可以通过执行以上VBS代码,来刷新详细信息视图的文件夹图标,并在目标文件列表中,创建任意文件,再删除该文件的方式(相比让Quicker循环创建VBS脚本,写入再运行会快很多),实现后台强制刷新文件夹属性缓存。

白云朔 最后更新于 2025/3/4

白云朔 2025-01-13 00:40 :

具体段落位置:


回复内容
瞑空凌 2025-01-13 16:17
#1

找到一点头绪,使用 IShellFolder::BindToObject 方法获取 IStorage 接口,然后调用 IStorage::Commit 方法
AI抛出来的IStorage 成员 (Microsoft.VisualStudio.OLE.Interop) |Microsoft 学习 --- IStorage Members (Microsoft.VisualStudio.OLE.Interop) | Microsoft Learn
还要找找有没有能运行的代码来验证这个😂


瞑空凌 2025-01-14 02:57
#3


绝对是这个,得再找找足够资料来参考怎么用

---似乎找错了
SHUpdateImageA 函数(以及它的宽字符版本 SHUpdateImageW)是用于通知Windows Shell,一个图标或图像列表中的图标已经发生了变化,需要更新。这个函数通常在你更新了应用程序的图标文件后调用,以确保Shell和其他使用系统图像列表的组件能够反映出这些更改。

瞑空凌 最后更新于 2025-01-16 16:52
瞑空凌 2025-01-17 14:03
#4

连续几天的搜索问AI,终于有些概念理解了😂.一直视而不见

...找错方向了,把接口和函数方法理解成一个意思了,我要的不是加功能而是使用原来的功能😂



借助AI把代码实现后,执行功能毫无反应....失败

瞑空凌 最后更新于 2025-01-25 22:53
瞑空凌 2025-01-28 02:33
#5

没啥事,再随缘找找看。😂


,还不会用找到的两个工具,感觉依旧找错了。。。不知道这个功能是干啥的,点应用就会出现调用,无论是否更改图标。

白云朔 回复 瞑空凌 1天20小时前 :

楼下有老哥给出了C#的实现方法,可以一起研究下

瞑空凌 回复 白云朔 1天15小时前 :

谢谢🤝🤝🤝🤝🤝🤝🤝🤝🤝🤝🤝🤝🤝

AzureHearted 1天20小时前
#6

下面是一个C#总调用SHGetSetFolderCustomSettings接口实现的一个设置文件夹图标以及移除文件夹图标的方法,这个方法可以即时生效(理论上应该也可以进行其他属性的刷新):

using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace FolderCustom
{
	/// <summary>
	/// 文件夹图标工具类
	/// </summary>
	public class IconTool
	{
	    /// <summary>
	    /// 设置文件夹图标
	    /// </summary>
	    /// <param name="dirPath">文件夹路径</param>
	    /// <param name="strFile">图标文件路径</param>
	    public static void SetFolderIcon(string dirPath, string filePath)
	    {
	        LPSHFOLDERCUSTOMSETTINGS FolderSettings = new LPSHFOLDERCUSTOMSETTINGS();
	        FolderSettings.dwMask = 0x10;
	        FolderSettings.pszIconFile = filePath;
	        FolderSettings.iIconIndex = 0;
	
	        //UInt32 FCS_READ = 0x00000001;
	        UInt32 FCS_FORCEWRITE = 0x00000002;
	        UInt32 FCS_WRITE = FCS_FORCEWRITE;
	
	        string pszPath = dirPath;
	        UInt32 HRESULT = SHGetSetFolderCustomSettings(ref FolderSettings, pszPath, FCS_WRITE);
	    }
	
	    [DllImport("Shell32.dll", CharSet = CharSet.Auto)]
	    private static extern UInt32 SHGetSetFolderCustomSettings(ref LPSHFOLDERCUSTOMSETTINGS pfcs, string pszPath, UInt32 dwReadWrite);
	
	    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
	    private struct LPSHFOLDERCUSTOMSETTINGS
	    {
	        public UInt32 dwSize;
	        public UInt32 dwMask;
	        public IntPtr pvid;
	        public string pszWebViewTemplate;
	        public UInt32 cchWebViewTemplate;
	        public string pszWebViewTemplateVersion;
	        public string pszInfoTip;
	        public UInt32 cchInfoTip;
	        public IntPtr pclsid;
	        public UInt32 dwFlags;
	        public string pszIconFile;
	        public UInt32 cchIconFile;
	        public int iIconIndex;
	        public string pszLogo;
	        public UInt32 cchLogo;
	    }
	    
	    /// <summary>
	    /// 移除文件夹图标
	    /// </summary>
	    /// <param name="folderPath">文件夹路径</param>
	    public static void RemoveFolderIcon(string folderPath)
		{
		    LPSHFOLDERCUSTOMSETTINGS settings = new LPSHFOLDERCUSTOMSETTINGS
		    {
		        dwSize = (uint)Marshal.SizeOf(typeof(LPSHFOLDERCUSTOMSETTINGS)),
		        dwMask = 0x00000010, // FCSM_ICONFILE
		        pszIconFile = null,
		        iIconIndex = 0
		    };
		
		    uint FCS_FORCEWRITE = 0x00000002;
		
		    uint hr = SHGetSetFolderCustomSettings(ref settings, folderPath, FCS_FORCEWRITE);
		    if (hr != 0)
		    {
		        Console.WriteLine("移除图标失败,HRESULT: 0x" + hr.ToString("X"));
		    }
		    else
		    {
		        Console.WriteLine("图标已移除。");
		    }
		
		    // 可选:删除 desktop.ini 和图标文件
//		    string desktopIniPath = Path.Combine(folderPath, "desktop.ini");
//		    if (File.Exists(desktopIniPath))
//		    {
//		        var attr = File.GetAttributes(desktopIniPath);
//		        File.SetAttributes(desktopIniPath, FileAttributes.Normal);
//		        File.Delete(desktopIniPath);
//		    }
		
		    // 可选:去掉文件夹的只读属性
		    var dirInfo = new DirectoryInfo(folderPath);
		    dirInfo.Attributes &= ~FileAttributes.ReadOnly;
		}
	}
}

AzureHearted 最后更新于 1天19小时前
白云朔 回复 AzureHearted 1天20小时前 :

哥们怎么删了

AzureHearted 回复 白云朔 1天20小时前 :

后面我想了一下,我这个方法主要是针对文件夹图标更换时候的刷新,所以我就删了

白云朔 回复 AzureHearted 1天20小时前 :

意思是只适用于刷新图标的缓存吗?就算是这样我觉得也没什么问题啊,可以挂着大家看看,或者看有没有大佬在此基础上给出更全面的办法

AzureHearted 回复 白云朔 1天20小时前 :

那行,我放出来给你们看看,我用C#写的这个,主要是调用SHGetSetFolderCustomSettings这个API

AzureHearted 最后更新于 1天20小时前
AzureHearted 回复 白云朔 1天20小时前 :

这个API我只实验过用它来修改文件夹图标,并且即时生效,其他我就没有尝试过了,你们可以研究研究

白云朔 回复 AzureHearted 1天20小时前 :

好的,顺便好奇老哥是从哪翻到这个API的?

AzureHearted 回复 AzureHearted 1天20小时前 :

我上面这个案例可以直接使用Quicker的C#执行模块生成程序集,然后注册后就能在Quicker环境下调用了,我最新的动作文件夹内嵌图标 - by AzureHearted - 动作信息 - Quicker就是这样实现的

白云朔 回复 AzureHearted 1天20小时前 :

不得不再次吐槽微软的文档检索功能了,找API是真的难(

AzureHearted 回复 白云朔 1天20小时前 :

这个API可以兼容到最老Window 2000

AzureHearted 回复 白云朔 1天20小时前 :
这种时候就应该问AI,有时候AI还是能给出一些意想不到的方案
AzureHearted 回复 白云朔 1天20小时前 :

这个API其实是Windows底层的一个API,用C语言写的,C#里面调用是通过 P/Invoke

白云朔 回复 AzureHearted 1天20小时前 :

问AI跟抽奖一样,纯凭运气,楼上的瞑空凌老哥问AI问了几层楼也没问出来好的(捂脸

白云朔 回复 AzureHearted 1天20小时前 :

嗯,我研究一下,顺便楼上的老哥我也回复了一下过来看

AzureHearted 回复 白云朔 1天20小时前 :

代码这块还是建议问chartGPT,国内的AI都不太行

AzureHearted 回复 白云朔 1天20小时前 :

我可以把我文件夹内嵌图标 - by AzureHearted - 动作信息 - Quicker这个动作的实现核心步骤给你参考,这个动作我也是最近才用这个API重构的,先加个联系方式

AzureHearted 最后更新于 1天20小时前
白云朔 回复 AzureHearted 1天19小时前 :

没事,知道有这个API其实就行了,我主要近期都在写一些通用的基础模块,筹备后续发一些其他动作,短期内应该没有太多精力去较大更新目前的这个动作了(因为目前耦合度有点高了,可能会整体使用新的模块和写法重构),考虑到这个API暂时只针对图标,对于其他属性的更新尚待研究,所以只能先鸽了(私密马赛

瞑空凌 回复 AzureHearted 1天15小时前 :

感谢大佬👍

回复主贴