windows – 如何获取IPreviewHandler文件扩展名?

前端之家收集整理的这篇文章主要介绍了windows – 如何获取IPreviewHandler文件扩展名?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
如何获取特定文件扩展名的 shell IPreviewHandler

背景

Windows允许开发人员为其自定义文件类型创建预览处理程序:

Preview handlers are called when an item is selected to show a lightweight,rich,read-only preview of the file’s contents in the view’s reading pane. This is done without launching the file’s associated application.

A preview handler is a hosted application. Hosts include the Windows Explorer in Windows Vista or Microsoft Outlook 2007.

我想利用现有的IPreviewHandler基础设施来获取文件缩略图.

在流中

问题是我的文件没有放在shell命名空间中(即它们不在硬盘上).它们坐在记忆中,可通过IStream访问.这意味着我无法使用传统的IExtractImage接口;因为它不支持从Stream加载文件.

幸运的是,这就是现代IPreviewHandler支持(推荐和更喜欢)从Stream加载数据的原因,并建议不要从文件加载预览:

This method is preferred to 07001 due to its ability to use streams that are not accessible through a Win32 path,such as the contents of a compressed file with a .zip file name extension.

那我怎么得到它?

没有关于获取与特定扩展名相关联的IPreviewHandler的正确方法的文档.但是,如果我采取如何注册IPreviewHandler的指示,and read the contract from the other side

HKEY_CLASSES_ROOT
  .xyz
     (Default) = xyzfile

HKEY_CLASSES_ROOT
   xyzfile
      shellex
         {8895b1c6-b41f-4c1c-a562-0d564250836f} //IPreviewHandler subkey
             (Default) = [clsid of the IPreviewHandler]

鉴于我知道扩展,我应该能够遵循相同的路线.让我们用一个真实世界的例子,一个.jpg文件

请注意,该文件具有预览.请注意,我添加了第二个屏幕截图,以强化预览不是来自硬盘驱动器上的文件的想法.

让我们得到spellunking

首先是它是一个.jpg文件

HKEY_CLASSES_ROOT
   .jpg
      (Default) = ACDC_JPG

HKEY_CLASSES_ROOT
   ACDC_JPG
      ShellEx
         {BB2E617C-0920-11d1-9A0B-00C04FC2D6C1}
         ContextMenuHandlers

等等,预览处理程序没有{8895b1c6-b41f-4c1c-a562-0d564250836f}子项.这必然意味着我们无法获取.jpg文件缩略图.

还原荒谬

真正的问题

细心的读者会意识到我要问的实际问题是:

How do i get the preview of an image contained only in a stream?

虽然这是一个有用的问题,而且我遇到的真正问题是,如何使用IPreviewHandler获得答案也是一个有用的问题.

所以随时回答;或两者!

奖金阅读

> MSDN:Preview Handlers and Shell Preview Host
> MSDN:How to Register a Preview Handler
> MSDN:IInitializeWithStream::Initialize method
> IPreviewHandler throws uncatchable exception
> Outlook IPreviewHandler for Delphi

@hvd有正确的答案.

文件类型具有ShellEx密钥,带有{guid}子密钥.每个{guid}键代表一个特定的InterfaceID.

有许多标准shell接口可以与文件类型相关联:

> {BB2E617C-0920-11d1-9A0B-00C04FC2D6C1} IExtractImage
> {953BB1EE-93B4-11d1-98A3-00C04FB687DA} IExtractImage2
> {e357fccd-a995-4576-b01f-234630154e96} IThumbnailProvider
> {8895b1c6-b41f-4c1c-a562-0d564250836f} IPreviewHandler

不受支持的未记录的注册表项的搜索

如果我想找到,例如,与.jpg文件关联的IPreviewHandler的clsid,我会查看:

HKEY_CLASSES_ROOT/.jpg/ShellEx/{8895b1c6-b41f-4c1c-a562-0d564250836f}
   (default) = [clsid]

但那不是我唯一能看的地方.我也可以看看:

HKEY_CLASSES_ROOT/.jpg
   (default) = jpgfile
HKEY_CLASSES_ROOT/jpgfile/ShellEx/{8895b1c6-b41f-4c1c-a562-0d564250836f}
   (default) = [clsid]

但那不是我唯一能看的地方.我也可以看看:

HKEY_CLASSES_ROOT/SystemFileAssociations/.jpg/ShellEx/{8895b1c6-b41f-4c1c-a562-0d564250836f}
   (default) = [clsid]

但那不是我唯一能看的地方.我也可以看看:

HKEY_CLASSES_ROOT/SystemFileAssociations/jpegfile/ShellEx/{8895b1c6-b41f-4c1c-a562-0d564250836f}
   (default) = [clsid]

但那不是我唯一能看的地方.如果我认为该文件是图像,我也可以查看:

HKEY_CLASSES_ROOT/SystemFileAssociations/image/ShellEx/{8895b1c6-b41f-4c1c-a562-0d564250836f}
   (default) = [clsid]

我是如何找到这些位置的?我是否只遵循记录和支持的位置?不,我在探索资源管理器时使用了Process Monitor,因为它正在寻找一个IThumbnailProvider.

不要使用无证件的拼写

所以现在我想自己使用标准的shell接口作为文件类型.这意味着我必须抓取位置.但是,为什么要以无证件,不受支持的方式抓取这些位置.为什么会在the thing以上从the guy发起愤怒?使用AssocQueryString

Guid GetShellClsidForFileType(String fileExtension,Guid interfaceID)
{
    //E.g.:
    //   String fileExtension = ".jpg"
    //   Guid   interfaceID   = "{8895b1c6-b41f-4c1c-a562-0d564250836f}"; //IExtractImage

    //The interface we're after - in string form
    String szInterfaceID := GuidToString(interfaceID);

    //Buffer to receive the clsid string
    DWORD bufferSize := 1024; //more than enough to hold a 38-character clsid
    String buffer;
    SetLength(buffer,bufferSize);

    HRESULT hr := AssocQueryString(
          ASSOCF_INIT_DEFAULTTOSTAR,ASSOCSTR_SHELLEXTENSION,//for finding shell extensions
          fileExtension,//e.g. ".txt"
          szInterfaceID,//e.g. "{8895b1c6-b41f-4c1c-a562-0d564250836f}"
          buffer,//will receive the clsid string
          @bufferSize);
   if (hr <> S_OK) 
      return Guid.Empty;

   Guid clsid;
   HRESULT hr = CLSIDFromString(buffer,out clsid);
   if (hr <> NOERROR) 
      return Guid.Empty;

   return clsid;
}

所以要获得.xps文件的IPreviewHandler的clsid:

Guid clsid = GetShellClsidForFileType(".xps",IPreviewHandler);

如何获得IPreviewHandler文件扩展名?

综上所述,我们现在可以回答这个问题:

IPreviewHandler GetPreviewHandlerForFileType(String extension)
{
    //Extension: the file type to return IPreviewHandler for (e.g. ".xps")
    Guid previewHandlerClassID = GetShellClsidForFileType(extension,IPreviewHandler);

    //Create the COM object
    IUnknown unk = CreateComObject(previewHandlerClassID);

    //Return the actual IPreviewHanler interface (not IUnknown)
    return (IPreviewhandler)unk;
}

猜你在找的Windows相关文章