首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在没有注册表的情况下加载IFilter

在没有注册表的情况下加载IFilter
EN

Stack Overflow用户
提问于 2012-10-23 06:35:20
回答 1查看 2.2K关注 0票数 2

因此,有人告诉我,我可能无法访问通常将其IFilters加载到系统上的注册表或程序,因此我必须将IFilter dll包含在应用程序中,并从那里直接加载它们。我目前正在使用CodeProject的C# IFilter类,但当涉及到filterPersistClass、persistentHandlerClass和COM时,它们仍然是我无法理解的一些事情,因此,我对如何使它工作有点不知所措。

我已经完成了所有平凡的事情,比如获取DLL,设置一个具有“扩展名,DLL路径”的资源文件,但是似乎无法掌握如何加载IFilter DLL。也许我应该从头开始,但我想我应该先寻求一些帮助。

编辑(部分解决方案)

我知道了如何使用query.dll中的FilterReader构造函数中的下面的代码加载PDFFilter.dll,尽管现在加载PDFFilter.dll文件时遇到了问题,并且得到了以下错误:

无法在DLL 'C:\Program \Adobe 9 for 64位LoadIFilter‘中找到名为“iFilter”的入口点

我认为我现在遇到的问题是,PDFFilter.dll使用STA,而C#应用程序是MTA。

代码语言:javascript
复制
[DllImport("query.dll", SetLastError = true, CharSet = CharSet.Unicode)]
static extern int LoadIFilter(string pwcsPath, [MarshalAs(UnmanagedType.IUnknown)] ref object pUnkOuter, ref IFilter ppIUnk);

// --------------------------- constructor ----------------------------------

var isFilter = false;
object iUnknown = null;

LoadIFilter(fileName, ref iUnknown, ref _filter);

var persistFile = (_filter as IPersistFile);
if (persistFile != null)
{
    persistFile.Load(fileName, 0);
    IFILTER_FLAGS flags;
    IFILTER_INIT iflags =
        IFILTER_INIT.CANON_HYPHENS |
        IFILTER_INIT.CANON_PARAGRAPHS |
        IFILTER_INIT.CANON_SPACES |
        IFILTER_INIT.APPLY_INDEX_ATTRIBUTES |
        IFILTER_INIT.HARD_LINE_BREAKS |
        IFILTER_INIT.FILTER_OWNED_VALUE_OK;

    if (_filter.Init(iflags, 0, IntPtr.Zero, out flags) == IFilterReturnCode.S_OK)
        isFilter = true;
}

if (_filter != null && isFilter) return;
if (_filter != null) Marshal.ReleaseComObject(_filter);
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-03-15 16:30:19

IFilter对象没有什么神奇之处。它们位于标准的COM dll中。最后,您需要类的clsid,它知道如何处理pdf文件。

LoadIFilter函数在query.dll中只是一个方便的辅助函数。它做的每一件事你都可以自己做。

在注册表中,有一种标准的方法,其中文件扩展名(例如.pdf)被解析为clsid (例如{E8978DA6-047F-4E3D-9C78-CDBE46041603})。

注意事项:您也可以跳到最后,并且知道的IFilter实现的clsid是{E8978DA6-047F-4E3D-9C78-CDBE46041603}。但这还不能保证,所以你需要爬行注册表。

.ext解析为实现IFilter的对象的clsid的算法是:

代码语言:javascript
复制
GetIFilterClassIDForFileExtension(String extension)   
    arguments:   
        extension (String) e.g. ".pdf"   
    returns:    
        clsid (Guid) e.g. 

    //Get the Persistent Handler for this extension
    //e.g. 
    //   HKLM\Software\Classes\.pdf\PersistentHandler\(Default)
    //returns
    //   "{F6594A6D-D57F-4EFD-B2C3-DCD9779E382E}"
    persistentHandlerGuid = HKLM\Software\Classes\.pdf\PersistentHandler\(Default)

    //Get the clsid associated with this persistent handler
    //e.g. 
    //   HKLM\Software\Classes\CLSID\{F6594A6D-D57F-4EFD-B2C3-DCD9779E382E}\PersistentAddinsRegistered\{89BCB740-6119-101A-BCB7-00DD010655AF}
    //where the final guid is the interface identifier (IID) of IFilter
    clsid = HKLM\persistentHandlerGuid\PersistentAddinsRegistered\{89BCB740-6119-101A-BCB7-00DD010655AF}

    //e.g. returns "{E8978DA6-047F-4E3D-9C78-CDBE46041603}", the clsid of Adobe's PDF IFilter
    return clsid

拥有适当对象的clsid后,可以使用以下方法创建该对象:

代码语言:javascript
复制
Guid clsid = GetIFilterClassForFileExtension(".pdf")
IFilter filter = CreateComObject(clsid);

现在您已经拥有了来自LoadIFilterquery.dll函数的全部内核。

代码语言:javascript
复制
IFilter LoadIFilter(String filename)
{
   String extension = ExtractFileExt(filename); //e.g. "foo.pdf" --> ".pdf"
   Guid clsid = GetIFilterClassForFileExtension(extension);
   return CreateComObject(clsid) as IFilter;
}

现在,所有这些仍然需要注册表,因为您仍然必须能够将一个clsid.扩展解析为如果您已经知道了分类,那么您不需要注册中心:

代码语言:javascript
复制
IFilter adobeIFilterForPdfs = CreateComObject("{E8978DA6-047F-4E3D-9C78-CDBE46041603}")

你可以走了。

重要的一点是,您试图调用的函数,LoadIFilter不在Adobe中(或任何其他公司提供的任何其他IFilter dll,用于爬行任何其他文件类型)。LoadIFilter函数是由query.dll导出的,它只是我所描述的步骤的助手函数。

所有的IFilter All都是COM All。载入COM dll的有文档记录的方法是通过CoCreateInstance函数:

代码语言:javascript
复制
IUnknown CreateComObject(Guid ClassID)
{
   IUnknown unk;

   HRESULT hr = CoCreateInstance(ClassID, null, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, IUnknown, ref unk);
   if (Failed(hr))
      throw new Exception("Could not create instance: "+hr);
   return unk;
}

我将让您找到从C#托管代码创建COM对象的正确方法。我都忘了。

注意事项:发布到公共域中的任何代码。不需要归属。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13024751

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档