首页 > 解决方案 > 如何在.Net最新版本中获取文件类型的IPreviewHandler

问题描述

最近在工作中,我收到一个项目,要求我预览特定文件类型并将其显示在预览窗格中(类似于 Windows 文件资源管理器中的预览窗格)。在对如何实现这一目标进行了 3 或 4 天的广泛研究之后,我完全被难住了。

起初我尝试关注这篇文章如何获取文件扩展名的 IPreviewHandler?但除了一些非常长的随机错误代码之外,我永远无法让 AssocQueryString 返回任何内容。在寻找另一种解决方案后,我偶然发现了这篇文章https://www.brad-smith.info/blog/archives/183在按照他的教程并下载示例代码之后,我能够生成 Word 文档的预览,但是不适用于任何其他文件类型。使这成为可能的代码是这里的这些行

var comType = Type.GetTypeFromCLSID(CurrentPreviewHandler, true);
_mCurrentPreviewHandler = Activator.CreateInstance(comType);

if (_mCurrentPreviewHandler is IPreviewHandler handler)
{
   // bind the preview handler to the control's bounds and preview the content
   var r = ClientRectangle;
   handler.SetWindow(Handle, ref r);
   handler.DoPreview();
   return true;
}

在使用调试器后,我发现 word 文档返回 System.__ComObject,而我试图为其生成预览的文件类型返回用于创建 ShellExtension 的类的实例。所以我回到互联网进行更多研究,发现了这个 CodeProject 示例https://www.codeproject.com/Articles/25465/Using-Vista-Preview-Handlers-in-a-WPF-Application。这个项目实际上为我正在寻找的文件类型生成了预览!我非常兴奋,直到我注意到该项目使用了与上面完全相同的代码生成预览!我非常困惑,直到我注意到两个项目的 System.dll 是不同的版本。一个有效的目标是 .Net 3.5,另一个目标是 .Net 4.6.1,这很不幸,因为我们的项目使用的是 .Net 4.6.1。

所以现在你已经跟上了速度,这是我的问题。无论如何,在 .Net 4.6.1 中是否可以像在 .Net 3.5 中一样获得文件的预览?有谁知道这两个版本之间有什么变化?或者也许有一种完全不同的方法可以更好地做到这一点?提前致谢!

PS 在 .Net 3.5 项目中使用调试器时,我注意到 Type.GetTypeFromCLSID 返回一个 System.__ComObject ,这也是它为 word 文档返回的内容。这有关系吗?此外,虽然 .Net 3.5 确实生成了预览,但它会引发此异常 System.Runtime.Serialization.SerializationException:“尝试反序列化空流。” 我不知道这是否有帮助,但我想我会包括它以防万一。

标签: c#.netcomobjectipreviewhandler

解决方案


经过大约一个半月的尝试,我终于找到了一个解决方案……有点。我发现 C++ API 函数仍然可以生成我的预览,所以我创建了一个 C++ dll 来生成我的预览。我在 C# 方面创建了一个边框元素,并将其子元素设置为从 HwndHost 继承的类,以便边框获得窗口句柄。然后,我将窗口句柄传递到我的 C++ dll 中,让 dll 负责绘制预览的其余工作。

我会第一个承认这不是一个完美的解决方案,但它现在可以预览。我在 Microsoft 的支持下提交了一份故障单,如果他们提出了比我在这里提供的更好的解决方案,我将在此提供。另外,如果有人对它的工作原理有任何疑问,请发表评论,我会尝试添加对我所做工作的更详细解释。


推荐阅读