Cloud File API同步根目录下已Hydrated文件缩略图获取异常排查
类OneDrive应用缩略图获取问题
我正在开发一款类OneDrive应用,通过Cloud File API将云端托管文件映射到用户本地文件夹。为优化UI显示,我希望从本地缓存文件获取缩略图,让用户在文件上传云端前就能查看本地编辑内容。
Windows资源管理器能正常显示该同步根目录下所有已Hydrated文件的缩略图,但我的C#代码通过P/Invoke调用Shell获取缩略图时,却无法稳定工作——不同文件类型都存在这个问题,且暂未找到触发规律。失败时GetImage调用会返回HRESULT错误码0x8004B207(对应WTS_E_NOSTORAGEPROVIDERTHUMBNAILHANDLER),这让我很困惑,因为资源管理器明明能正常显示。
我的简化版代码如下(已省略错误处理):
[ComImportAttribute()] [GuidAttribute("bcc18b79-ba16-442f-80c4-8a59c30c463b")] [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] public interface IShellItemImageFactory { HResult GetImage( [In, MarshalAs(UnmanagedType.Struct)] SIZE size, [In] SIIGBF flags, [Out] out IntPtr phbm); } [DllImport("shell32.dll", CharSet = CharSet.Unicode, PreserveSig = false)] [return: MarshalAs(UnmanagedType.Interface, IidParameterIndex = 2)] public static extern IShellItemImageFactory SHCreateItemFromParsingName( [In][MarshalAs(UnmanagedType.LPWStr)] string pszPath, [In] IntPtr pbc, [In][MarshalAs(UnmanagedType.LPStruct)] Guid riid); [DllImport("gdi32.dll", EntryPoint = "DeleteObject")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool DeleteObject( [In] IntPtr hObject); [Flags] public enum SIIGBF { SIIGBF_RESIZETOFIT = 00, SIIGBF_BIGGERSIZEOK = 01, SIIGBF_MEMORYONLY = 02, SIIGBF_ICONONLY = 04, SIIGBF_THUMBNAILONLY = 08, SIIGBF_INCACHEONLY = 10 } public Bitmap GetThumbnail(string parsingName) { // 获取IShellItemImageFactory接口 IShellItemImageFactory isiif = null; Guid iid = typeof(IShellItemImageFactory).GUID; isiif = SHCreateItemFromParsingName(parsingName, IntPtr.Zero, iid); if (isiif == null) return null; // 提取内存位图 SIIGBF flags = SIIGBF.SIIGBF_BIGGERSIZEOK | SIIGBF.SIIGBF_THUMBNAILONLY; IntPtr hBitmap = IntPtr.Zero; HResult result = isiif.GetImage(new SIZE(256, 256), flags, out hBitmap); Marshal.FinalReleaseComObject(isiif); if (hBitmap == IntPtr.Zero) return null; Bitmap bmp = Image.FromHbitmap(hBitmap); DeleteObject(hBitmap); return bmp; }
这段代码在普通文件夹中100%有效,但在Cloud File API同步根目录下不稳定。
我还尝试过绕过Shell直接生成缩略图,步骤如下:
- 获取文件扩展名,在
HKEY_CLASSES_ROOT中查找对应的IThumbnailProviderCLSID - 通过CLSID找到
IThumbnailProvider实现 - 根据其支持方式,传入流或文件实例化
IThumbnailProvider - 调用该实例的
GetThumbnail方法
这种方式不仅可靠性存疑,而且生成的缩略图不会被Shell缓存——即便我用这种方式生成了缩略图,后续调用原有代码还是无法获取到。我希望Shell能缓存缩略图,确保无论哪个进程首次查看文件,只需要生成一次。
我有三个具体问题:
- 如何通过编程方式获取资源管理器中已经显示的缩略图,用于我的应用UI?
- 直接通过文件类型的
IThumbnailProvider生成缩略图是否安全? - 如何让Shell缓存我生成的缩略图,避免重复生成?
内容的提问来源于stack exchange,提问作者Travis R
相关产品推荐
相关产品推荐

