You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Win10下SHCNE_CREATE事件触发后IShellItem2无法获取文件时间如何解决

问题原因

SHCNE_CREATE是Shell发出的文件系统对象创建完成的早期通知,触发时Shell的命名空间属性缓存尚未完成同步更新,你通过PIDL创建的IShellItem2实例默认读取的是未完成初始化的缓存数据,文件创建时间、修改时间这类扩展属性还未被写入缓存,因此会返回ERROR_NOT_FOUND错误。
你调试时能看到文件完整属性、GetDisplayName()调用正常,是因为:调试中断的时间差足够让Shell完成属性缓存同步,资源管理器访问属性时会主动触发磁盘读取而非只读过期缓存;而文件名属于PIDL自带的基础属性,不依赖额外的属性缓存就能读取。

可行解决方案
  • 方案1:异步延迟读取
    收到SHCNE_CREATE通知后,不要在回调函数内立刻读取时间属性,投递一个延迟100~500ms的异步任务后再执行属性读取操作,给Shell属性缓存留出同步时间,注意不要在通知回调线程内做同步等待,避免阻塞Shell消息队列。
  • 方案2:强制刷新IShellItem2属性缓存
    拿到IShellItem2实例后先调用Update()方法强制从磁盘同步最新属性,刷新完成后即可正常读取时间属性,该方案可靠性高于固定延迟,不受系统负载影响。
    参考代码:
    IShellItem2* pShellItem = nullptr;
    HRESULT hr = SHCreateItemFromIDList(pidlReceived, IID_PPV_ARGS(&pShellItem));
    if (SUCCEEDED(hr)) {
        // 强制同步磁盘最新属性
        hr = pShellItem->Update(NULL);
        if (SUCCEEDED(hr)) {
            FILETIME ftCreate;
            hr = pShellItem->GetFileTime(PKEY_DateCreated, &ftCreate);
            // 此处hr为S_OK即可正常获取创建时间
        }
        pShellItem->Release();
    }
    
  • 方案3:绕过Shell缓存直接读取
    先调用IShellItem2::GetDisplayName(SIGDN_FILESYSPATH, &pszFilePath)获取文件的本地完整路径,再通过Win32原生APIGetFileAttributesExW()或者CreateFileW + GetFileTime直接读取文件时间属性,该方案完全不依赖Shell缓存状态,稳定性最高。

内容的提问来源于stack exchange,提问作者user3161924

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 03:48:01