gpt4 book ai didi

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

转载 作者:可可西里 更新时间:2023-11-01 12:51:05 33 4
gpt4 key购买 nike

我如何获得外壳 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 Initialize 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 文件:

enter image description here

enter image description here

请注意该文件有一个预览。请注意,我包含第二个屏幕截图只是为了强调预览并非来自硬盘驱动器上的文件。

让我们得到 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 的答案也是一个有用的问题。

所以请随意回答;或两者兼而有之!

红利阅读

最佳答案

@hvd 的答案是正确的。

文件类型有一个 ShellEx 键和 {guid} 子键。每个 {guid} 键代表一个特定的 InterfaceID

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

  • {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 文件关联的 IPreviewHandlerclsid,我会查找:

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]

我是如何找到这些位置的?我是否只关注记录和支持的位置?不,我在 Explorer 寻找 IThumbnailProvider 时使用 Process Monitor 监视它。

不要使用未记录的拼写

所以现在我想自己使用一个文件类型的标准 shell 接口(interface)。这意味着我必须抓取这些位置。但为什么要以未记录、不受支持的方式抓取这些位置。为什么要激怒the guy从高处the thing ?使用 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 文件的 IPreviewHandlerclsid:

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 - 如何获取文件扩展名的 IPreviewHandler?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23633246/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com