测试筛选器处理程序

IFilter 测试套件验证筛选器处理程序。 测试套件通过以下方式执行此操作:调用 IFilter 方法并检查返回的值是否符合 IFilter 接口规范;检查区块标识符是否唯一且不断增加、 IFilter 接口在重新初始化后的行为是否一致,以及任何具有无效参数的 IFilter 方法调用是否返回预期的错误代码。 测试套件程序还会转储由筛选器处理程序筛选的文件的输出,并在注册表中检查 IFilter 注册信息。

本主题的组织方式如下:

注意

如果正在安装某个文件类型的新筛选器处理程序作为现有筛选器注册的替换,安装程序应保存当前注册,并在卸载新的筛选器处理程序时还原它。 没有链接筛选器的机制。 因此,新的筛选器处理程序负责复制旧筛选器的任何必要功能。

Command-Line调用

IFilter 测试套件由三个命令行应用程序( ifilttst.exefiltdump.exefiltreg.exe)和初始化文件 ifilttst.ini组成。

重要

在 Windows 7 及更高版本中,显式阻止使用托管代码编写的筛选器。 由于潜在的公共语言运行时 (CLR) 运行多个加载项的进程的版本控制问题,筛选器必须使用本机代码编写。

ifilttst.exe

ifilttst.exe程序运行多个测试来验证筛选器处理程序。 以下示例演示如何从命令行调用 ifilttst.exe 程序:

ifilttst /i test.htm /l /d /v 1

该示例执行以下任务:

  • 指示程序筛选文件test.htm
  • 将日志消息重定向到 test.htm.log
  • 将转储消息重定向到 test.htm.dmp
  • 将详细程度设置为 1

要使上述命令正常工作,三个文件必须位于当前工作目录中: test.htmifilttst.exeifilttst.ini。 下表中列出了命令行开关。

切换和可能的变量 说明
/i 文件名 要筛选的输入文件或目录。 文件名可以包含通配符 *?
/我 日志消息定向到文件而不是屏幕。 日志消息描述所执行的各个测试以及测试的通过/失败结果。 日志文件名与输入文件名相同,但扩展名为 .log。
/d 转储消息定向到文件而不是屏幕。 转储消息描述区块的内容。 当详细级别为 3 时,将转储区块结构。 转储文件名与输入文件名相同,但扩展名为 .dmp。
/-我 禁用日志记录。 此标志将 /l 替代开关。
/-D 禁用转储。 此标志将 /d 替代开关。
/v integer 详细级别。 默认值为 3。
  • 0 - 测试仅记录有关特定 IFilter 接口故障的消息。 测试将转储区块内容。
  • 1 - 测试记录警告消息以及级别 0 的警告消息。
  • 2 - 测试记录有关通过的测试以及级别 1 的测试的消息。
  • 3 - 测试记录信息性消息以及级别 2 的消息。 此外,测试会转储区块的结构。
/t integer 要启动的线程数。 默认值为 1。
/r integer] 递归筛选子目录。 可选的整数参数指定要执行递归的深度。 如果未指定整数,或者整数为 0,则假定为完全递归。 默认情况下,递归深度为 1。
/c integer 要循环的次数。 如果整数为 0,则测试将无限循环。 默认情况下,测试仅循环一次。

注意

必须在命令行开关和值之间包括一个空格。

filtdump.exe

filtdump.exe程序加载指定文档的筛选器处理程序,并打印 IFilter DLL 生成的输出。 以下示例演示如何调用 filtdump.exe 程序。

filtdump filename.ext

Filtdump.exe使用 ILoadFilter::LoadIFilter 方法加载适用于指定文件扩展名的 IFilter DLL 并打印结果。 例如,以下命令指示filtdump.exe加载扩展名 .smp 的smpfilt.dll筛选器处理程序,从文件 myfile.smp 中提取所有文本和属性,然后打印结果。

filtdump myfile.smp

filtreg.exe

filtreg.exe程序检查注册表中的 IFilter 安装信息。 通过键入程序的名称从命令行调用filtreg.exe程序,如以下示例所示。

filtreg

Filtreg.exe通过打印文件扩展名和扩展名的 IFilter DLL 的名称来枚举具有与之关联的筛选器处理程序的所有文件扩展名。 这是验证 IFilter 是否正确安装的简单方法。

ifilttst.ini

通过调用 IFilter::Init 方法初始化 IFilter 接口。 IFilter::Init 方法采用以下四个参数:

  1. grfFlags
  2. cAttributes
  3. aAttributes
  4. pdwFlags

IFilter 测试套件的 ifilttst.exe 程序的用户可以在名为 ifilttst.ini 的文件中指定这些参数的值。 下表描述了ifilttst.ini文件中指定前三个参数 (输入参数) 的条目。 有关示例文件,请参阅 示例ifilttst.ini文件

注意

pdwFlags 参数没有表条目,因为它是输出参数;在调用 IFilter::Init 方法之前,它不需要具有任何特殊值。

  条目 说明
Flags 由 OR 运算符联接以构成 IFilter::Init 方法的 grfFlags 参数的IFILTER_INIT标志的名称。 标志名称必须全部为大写,并且位于同一行中。
cAttributes 一个十进制整数,表示 cAttributes 参数的值。
aAttributes 此条目必须以 aAttributes 开头 ,并且必须与 节中的其他 aAttributes 条目不同。 aAttributes 条目的法定名称为:aAttributesaAttributes1aAttributes2 等。 第一个令牌必须是 GUID。 GUID 的格式必须完全如示例ifilttst.ini文件的 部分所示[Test3]。 第二个标记可以是由十六进制表示法中的数字组成的 PID) (属性标识符,也可以是指向 lpwstr) (宽字符串的指针。 可以通过将字符串括在双引号中来指定 lpwstr,如示例ifilttst.ini文件的 部分所示 [Test6]

如果未指定 Flags 和 cAttributes 条目,则它们默认为 0。 如果将 cAttributes 设置为等于 2,则应指定两 个 aAttributes 名称。 [Test5]在示例的 部分中,cAttributes 为 1,但未指定任何 aAttributes。 然后,测试调用 cAttributes 等于 1 且 aAttributes 等于 NULLIFilter::Init 方法。 这是一个有用的测试用例,因为它可能会导致 IFilter::Init 方法中的访问冲突。

如果ifilttst.exe在工作目录中找不到名为 ifilttst.ini 的文件,则使用默认配置来初始化 IFilter::Init 对象。 以下示例演示了默认配置。

[default]
            grfFlags = IFILTER_INIT_APPLY_INDEX_ATTRIBUTES
            cAttributes = 0

示例ifilttst.ini文件

ifilttst.ini文件按节进行组织,节名称用方括号括起来。 在示例中,这些部分命名为 [Test1][Test2]等。 所有节名称必须唯一。 测试读取第一节中的值,并使用这些值初始化 IFilter 。 然后,使用此 IFilter 配置运行所有测试。 然后,使用上面列出的参数释放并重新初始化 IFilter 。 此过程会重复,直到所有配置都经过测试。

; Only extract text from the object
            [Test1]
            Flags =
            cAttributes = 0

            // Get all attributes (text-type and internal value-type properties.
            [Test2]
            Flags = IFILTER_INIT_APPLY_INDEX_ATTRIBUTES
            cAttributes = 0

            // This also extracts just text from the object (the GUID is PSGUID_STORAGE, and the propid is
            // PID_STG_CONTENTS).
            [Test3]
            Flags = IFILTER_INIT_CANON_PARAGRAPHS IFILTER_INIT_HARD_LINE_BREAKS
            cAttributes = 1
            aAttributes1 = b725f130-47ef-101a-a5f1-02608c9eebac 13

            // Only extract requested attribute from the html object (the GUID corresponds to the HTML IFilter.
            [Test4]
            Flags = IFILTER_INIT_CANON_HYPHENS IFILTER_INIT_CANON_SPACES
            cAttributes = 1
            aAttributes1 = 70eb7a10-55d9-11cf-b75b-00aa0051fe20 2

            // Question: what happens if cAttributes is nonzero, but aAttributes is empty?
            [Test5]
            Flags = IFILTER_INIT_CANON_SPACES IFILTER_INIT_APPLY_INDEX_ATTRIBUTES IFILTER_INIT_APPLY_OTHER_ATTRIBUTES
            cAttributes = 1

            // Here is an attribute with a lpwstr instead of a propid (the lpwstr is enclosed in quotes).
            // The GUID corresponds to the meta tag clsid for the HTML IFilter.
            [Test6]
            Flags =
            cAttributes = 1
            aAttributes1 = D1B5D3F0-C0B3-11CF-9A92-00A0C908DBF1 "GENERATOR"

IFilter 测试过程

初始化 IFilter 后,ifilttst.exe程序对 IFilter 执行一系列测试。 除了遵循 IFilter 测试过程外,请确保 IFilter 实现采用安全代码做法。 请参阅在 Windows 搜索中 实现筛选器处理程序中的“Windows 搜索的安全代码做法”。

验证测试

验证测试一次通过一个区块遍历对象,验证每个单独的区块和所有返回代码。 验证测试将所有返回 STAT_CHUNK 结构保存在列表中。

验证测试验证以下条件:

  • STAT_CHUNKidChunk 区块 ID 必须唯一且不断增加。
  • STAT_CHUNKflags 参数是已识别的区块状态,例如 CHUNKSTATE、CHUNK_TEXT或CenabledHUNK_VALUE常量。
  • STAT_CHUNKbreakType 参数是识别的中断类型 (0、1、2、3、4) 。
  • 如果 IFilter 初始化属性指定 IFilter 应仅返回包含内部值类型属性的区块,则 idChunkSource 必须等于 0。
  • 如果区块不是派生的,则如果它不是内部值类型属性,则 STAT_CHUNKidChunkSource 必须等于 STAT_CHUNKidChunk
  • IFilter::GetChunk 返回S_OK或其他可接受的返回值,例如FILTER_E_END_OF_CHUNKS、FILTER_E_LINK_UNAVAILABLE等。
  • 如果区块包含文本, 则 IFilter::GetText 返回S_OK、FILTER_S_LAST_TEXT或FILTER_E_NO_MORE_TEXT。
  • 如果 IFilter::GetText 返回FILTER_S_LAST_TEXT,则对 IFilter::GetText 的下一次调用将返回FILTER_E_NO_MORE_TEXT。
  • 如果区块包含值, 则 IFilter::GetValue 返回S_OK或FILTER_E_NO_MORE_VALUES。

一致性测试

ifilttxt.exe程序使用与验证测试中相同的参数重新初始化 IFilter 接口,并执行一致性测试。 如果已使用 IFILTER_INIT IFILTER_INIT_INDEXING_ONLY 标志初始化 IFilter 实现,则测试会释放 IFilter 接口,并在再次调用 IFilter::Init 方法之前将其重新绑定。

一致性测试验证以下条件:

无效的输入测试

ifilttst.exe程序使用相同的参数重新初始化 IFilter 接口,并执行无效的输入测试。 此测试一次执行一个区块,使函数调用不正确,例如在当前 chuck 包含文本时调用 IFilter::GetValue 方法。 该测试检查所有返回代码是否符合 IFilter 规范。

无效的输入测试验证以下条件:

注意

无效输入测试会将当前区块结构与验证测试中返回的结构进行比较,以确保它们相同。

测试不同的 IFilter 配置

ifilttst.exe程序释放 IFilter 接口和重新绑定,这次使用下一组参数对其进行初始化。 测试将重复以下周期:验证测试、一致性测试和无效输入测试,直到测试ifilttst.ini文件中指定的所有所需 IFilter 配置。

确保为已注册的项编制索引

IFilter 的最终测试可确保正确注册 IFilter,并调用它为注册的项编制索引以使用它。 可以使用目录管理器启动重新编制索引,或使用爬网范围管理器 (CSM) 设置默认规则,以指示希望索引器爬网的 URL。 索引编制完成后,使用 Windows 搜索 UI 在项的内容或属性中搜索字符串。 如果为项编制了索引,它们将显示在搜索结果中。

有关重新编制索引的详细信息,请参阅 使用目录管理器 和使用 爬网范围管理器。 ReindexMatchingUrls 代码示例演示了如何指定要重新编制索引的文件以及如何重新编制索引。 CrawlScopeCommandLine 代码示例演示如何定义爬网范围管理器的命令行选项 (CSM) 索引操作。 GitHub 上提供了这两个代码示例。

示例日志文件

根据请求,Ifilttst.exe程序可以生成一个日志,其中包含在执行过程中所执行步骤的说明。 以下示例摘自日志文件,详细程度设置为可能的最高值 3。

            1. INFO----**** New configuration ****
            2.
            3. Section name : Test2
            4. grfFlags     : 63
            5. cAttributes  : 0
            6. aAttributes  : NONE
            7. pdwFlags     : 0
            8.
            9. INFO----Successfully bound filter.
            10.
            11. PASS----Init() returned a valid value for pdwFlags.
            12.
            13. INFO----Successfully initialized filter.
            14.
            15. INFO----Performing validation test. In this part of the test, the chunks structures
            16.         returned by the IFilter are checked for correctness, and the return values
            17.         of the IFilter calls are checked.
            18.
            19. PASS----GetChunk() succeeded.
            20.
            21. PASS----The current chunk has a legal value for the flags field.

第一行是一条信息性消息,指示已从 ifilttst.ini 文件加载了新配置。 第 3 行 () 指示从中读取当前配置的ifilttst.ini文件中的节名称。 行 (4) 到 (7) 列出 IFilter::Init 的参数。 以 INFO 开头的行是有关 IFilter 绑定和验证测试开始的信息性消息。 以 PASS 开头的行是有关已通过的特定测试的消息。

以下日志示例中的行是警告。 警告提醒人们注意存在问题的 IFilter 行为,尽管是合法的。 此警告指示 IFilter::GetChunk 方法返回了不包含任何文本的文本区块。

WARNING-First call to GetText() returned FILTER_E_NO_MORE_TEXT.

以下示例错误消息指示 IFilter 发出了未请求的区块。

            ERROR---The IFilter has emitted a chunk which it was not requested to emit.
            Check the initialization parameters in section Test1 of the initialization file.
            INFO----Current chunk propid : 0x5

对于此示例错误消息, IFilter 发出了 PID 为 的 0x5区块。 检查 ifilttst.ini 中的部分 [Test1] 会表明 ,IFilter 已配置为不发出具有此 PID 的区块。 例如,如果在 Flags 条目中既未指定IFILTER_INIT_APPLY_INDEX_ATTRIBUTES,也没有指定IFILTER_INIT_APPLY_OTHER_ATTRIBUTES,并且 cAttributes 为 0,则 IFilter 将仅发出 PID 为 0x13 且对应于PID_STG_CONTENTS的区块。

示例转储文件

根据请求,Ifilttst.exe程序可以生成一个转储,其中包含它找到的区块及其内容。 以下示例是此类转储文件的摘录。

                1. Chunk ID: ........... 2
                2. Chunk Break Type: ... END OF SENTENCE
                3. Chunk State: ........ TEXT
                4. Chunk Locale: ....... 0x411
                5. Chunk Source ID: .... 2
                6. Chunk Start Source .. 0x0
                7. Chunk Length Source . 0x0
                8. GUID ................ b725f130-47ef-101a-a5f1-02608c9eebac
                9. Property ID ......... 0x13

                10. This is a HTML IFilter test page

                11. Chunk ID: ........... 3
                12. Chunk Break Type: ... END OF SENTENCE
                13. Chunk State: ........ TEXT
                14. Chunk Locale: ....... 0x411
                15. Chunk Source ID: .... 2
                16. Chunk Start Source .. 0x0
                17. Chunk Length Source . 0x0
                18. GUID ................ f29f85e0-4ff9-1068-ab91-08002b27b3d9
                19. Property ID ......... 0x2

                20. This is a HTML IFilter test page

                21. Chunk ID: ........... 4
                22. Chunk Break Type: ... END OF SENTENCE
                23. Chunk State: ........ VALUE
                24. Chunk Locale: ....... 0x411
                25. Chunk Source ID: .... 2
                26. Chunk Start Source .. 0x0
                27. Chunk Length Source . 0x0
                28. GUID ................ f29f85e0-4ff9-1068-ab91-08002b27b3d9
                29. Property ID ......... 0x2

                30. This is an HTML IFilter test page

前九行描述当前区块结构。 GUID 和 PID 对应于 PSGUID_STORAGE/PID_STG_CONTENTS。 这是包含纯文本的区块。 文本采用以下区块结构:

10. This is an HTML IFilter test page

下一个区块(从第 11 行开始)具有不同的 GUID(对应于 ) HTML IFilter和对应于 HTML HREF 的不同 PID。 这是由 HTML IFilter导出的内部值类型属性。

下一个区块(从第 21 行开始)具有相同的 GUID 和 PID,但其区块状态为 VALUE 而不是 TEXT。 请注意,最后两个区块中的文本与第一个区块的文本相同。 但是,由于 IFilter 设计用于将三个属性 (纯文本、HTML HREF 作为文本,HTML HREF 作为值) 应用于此短语,因此将在三个单独的区块中发出结果。

其他资源

开发筛选器处理程序

关于 Windows 搜索中的筛选器处理程序

在 Windows 搜索中创建筛选器处理程序的最佳做法

从筛选器处理程序返回属性

随 Windows 一起随附的筛选器处理程序

在 Windows 搜索中实现筛选器处理程序

注册筛选器处理程序