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

时间:2012-10-23 06:35:20

标签: c# com ifilter

所以我被告知我可能无法访问通常将IFilter加载到系统上的注册表或程序,所以我必须在应用程序中包含IFilter dll并直接从那里加载它们。我目前正在使用CodeProject的C#IFilter类,但是当涉及到filterPersistClass,persistentHandlerClass和COM时,它们仍然是我的头脑中的一些东西,因此我对如何使其工作有点迷失。 / p>

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

编辑(部分解决方案)

我想知道如何在FilterReader.cs的FilterReader构造函数中使用下面的代码加载query.dll,虽然我现在遇到问题,现在加载PDFFilter.dll文件并收到以下错误:

无法在DLL'C:\ Program Files \ Adob​​e \ Adob​​e PDF iFilter 9 for 64位平台\ bin \ PDFFilter.dll'

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

[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);

1 个答案:

答案 0 :(得分:4)

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

LoadIFilter中的query.dll函数只是一个方便的辅助函数。它所做的一切都可以自己做。

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

  

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

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

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后,可以使用以下命令创建它:

Guid clsid = GetIFilterClassForFileExtension(".pdf")
IFilter filter = CreateComObject(clsid);

您现在拥有来自LoadIFilter的{​​{1}}函数的全部内容:

query.dll

现在,所有这些仍然需要注册表,因为您仍然必须能够将扩展名解析为 IFilter LoadIFilter(String filename) { String extension = ExtractFileExt(filename); //e.g. "foo.pdf" --> ".pdf" Guid clsid = GetIFilterClassForFileExtension(extension); return CreateComObject(clsid) as IFilter; } 。如果您已经知道classid,那么您不需要注册表:

clsid

你很高兴。

重要的一点是,您尝试调用的函数IFilter adobeIFilterForPdfs = CreateComObject("{E8978DA6-047F-4E3D-9C78-CDBE46041603}") 不在Adobe的dll(或任何其他公司提供的任何其他IFilter dll,以抓取任何其他文件类型)中。 LoadIFilter函数由LoadIFilter导出,并且只是我所描述的上述步骤的辅助函数。

所有query.dll dll都是COM dll。记录的加载COM dll的方法是通过IFilter函数:

CoCreateInstance

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

  

注意:任何已发布到公共领域的代码。无需归属。