Testando manipuladores de filtro

O conjunto de testes IFilter valida os manipuladores de filtro. O conjunto de testes faz isso chamando métodos IFilter e verificando os valores retornados quanto à conformidade com a especificação da interface IFilter ; e verificando se os identificadores de partes são exclusivos e crescentes, se a interface IFilter se comporta consistentemente após a reinicialização e se qualquer método IFilter chamado com parâmetros inválidos retorna códigos de erro esperados. Os programas do conjunto de testes também despejam a saída de um arquivo filtrado por um manipulador de filtro e marcar as informações de registro de IFilter no registro.

Este tópico é organizado da seguinte maneira:

Observação

Se um novo manipulador de filtro para um tipo de arquivo estiver sendo instalado como uma substituição para um registro de filtro existente, o instalador deverá salvar o registro atual e restaurá-lo se o novo manipulador de filtro estiver desinstalado. Não há mecanismo para encadear filtros. Portanto, o novo manipulador de filtro é responsável por replicar qualquer funcionalidade necessária do filtro antigo.

Invocação Command-Line

O conjunto de testes IFilter consiste em três aplicativos de linha de comando : ifilttst.exe, filtdump.exee filtreg.exe e um arquivo de inicialização, ifilttst.ini.

Importante

No Windows 7 e posterior, os filtros escritos em código gerenciado são explicitamente bloqueados. Os filtros DEVEM ser escritos em código nativo devido a possíveis problemas de controle de versão do CLR (Common Language Runtime) com o processo em que vários suplementos são executados.

ifilttst.exe

O programa ifilttst.exe executa vários testes para validar um manipulador de filtro. O exemplo a seguir ilustra como invocar o programa ifilttst.exe da linha de comando:

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

O exemplo executa as seguintes tarefas:

  • Direciona o programa para filtrar o arquivo test.htm
  • Redireciona as mensagens de log para test.htm.log
  • Redireciona as mensagens de despejo para test.htm.dmp
  • Define o detalhamento como 1

Para que o comando anterior funcione, três arquivos devem estar localizados no diretório de trabalho atual: test.htm, ifilttst.exee ifilttst.ini. As opções de linha de comando são listadas na tabela a seguir.

Alternar e possíveis variáveis Descrição
/i nome do arquivo O arquivo de entrada ou diretório a ser filtrado. O nome do arquivo pode conter os caracteres * curinga e ?.
/l As mensagens de log são direcionadas para um arquivo em vez da tela. As mensagens de log descrevem os testes individuais executados e os resultados de aprovação/falha dos testes. O nome do arquivo de log é o mesmo que o nome do arquivo de entrada, mas com uma extensão .log.
/d Mensagens de despejo são direcionadas para um arquivo em vez da tela. Mensagens de despejo descrevem o conteúdo das partes. A estrutura da parte é despejada quando o nível de detalhamento é 3. O nome do arquivo de despejo é o mesmo que o nome do arquivo de entrada, mas com uma extensão .dmp.
/-L Desabilite o registro em log. Esse sinalizador substitui a opção /l .
/-D Desabilite o despejo. Esse sinalizador substitui a opção /d .
/v inteiro O nível de detalhes. O padrão é 3.
  • 0 – O teste registra apenas mensagens relacionadas a falhas específicas da interface IFilter . O teste despeja o conteúdo da parte.
  • 1 - O teste registra mensagens de aviso, bem como aquelas para o nível 0.
  • 2 – O teste registra em log mensagens relativas a testes aprovados, bem como aqueles para o nível 1.
  • 3 – O teste registra mensagens informativas, bem como aquelas para o nível 2. Além disso, o teste despeja a estrutura da parte.
/t inteiro O número de threads a serem iniciados. O padrão é 1.
/r inteiro] Filtra recursivamente subdiretórios. O parâmetro inteiro opcional especifica a profundidade para a qual a recursão deve ser exercida. Se nenhum inteiro for especificado ou se o inteiro for 0, a recursão completa será assumida. Por padrão, a profundidade de recursão é 1.
/c inteiro O número de vezes que o loop será executado. Se o inteiro for 0, o teste será executado infinitamente. Por padrão, o teste executa loops apenas uma vez.

Observação

Você deve incluir um espaço entre a opção de linha de comando e o valor .

filtdump.exe

O programa filtdump.exe carrega um manipulador de filtro para um documento especificado e imprime a saída produzida pela DLL IFilter . O exemplo a seguir ilustra como invocar o programa filtdump.exe.

filtdump filename.ext

Filtdump.exe usa o método ILoadFilter::LoadIFilter para carregar a DLL IFilter apropriada para a extensão de nome de arquivo especificada e imprime os resultados. Por exemplo, o comando a seguir instrui filtdump.exe a carregar o manipulador de filtro smpfilt.dll para a extensão .smp, extrair todo o texto e as propriedades do arquivo myfile.smp e imprimir os resultados.

filtdump myfile.smp

filtreg.exe

O programa filtreg.exe inspeciona as informações de instalação do IFilter no registro. Você invoca o programa filtreg.exe da linha de comando digitando seu nome, como no exemplo a seguir.

filtreg

Filtreg.exe enumera todas as extensões de nome de arquivo que têm manipuladores de filtro associados a elas imprimindo a extensão de nome de arquivo e o nome da DLL IFilter para a extensão. Essa é uma maneira simples de verificar a instalação correta de um IFilter.

ifilttst.ini

Uma interface IFilter é inicializada chamando o método IFilter::Init . O método IFilter::Init usa os quatro parâmetros a seguir:

  1. Grfflags
  2. cAttributes
  3. aAttributes
  4. Pdwflags

O usuário do programa ifilttst.exe do conjunto de testes IFilter pode especificar os valores desses parâmetros em um arquivo chamado ifilttst.ini. A tabela a seguir descreve as entradas no arquivo ifilttst.ini que especificam os três primeiros parâmetros (os parâmetros de entrada). Para obter um arquivo de exemplo, consulte Arquivo de ifilttst.ini de exemplo.

Observação

Não há nenhuma entrada de tabela para o parâmetro pdwFlags porque ele é um parâmetro de saída; ele não precisa ter nenhum valor especial antes da chamada para o método IFilter::Init .

  Entrada Descrição
Flags Os nomes dos sinalizadores IFILTER_INIT que devem ser unidos pelo operador OR para formar o parâmetro grfFlags do método IFilter::Init . Todos os nomes de sinalizador devem estar em maiúsculas e na mesma linha.
cAttributes Um inteiro decimal que representa o valor do parâmetro cAttributes .
aAttributes Essa entrada deve começar com aAttributes e deve ser diferente das outras entradas aAttributes dentro da seção . Os nomes legais para a entrada aAttributes são: aAttributes, aAttributes1, aAttributes2 e assim por diante. O primeiro token deve ser um GUID. O GUID deve ser formatado exatamente como ilustrado na [Test3] seção do Arquivo de ifilttst.ini de Exemplo. O segundo token pode ser um PID (identificador de propriedade) que consiste em um número em notação hexadecimal ou um ponteiro para uma cadeia de caracteres largos (lpwstr). Um lpwstr pode ser especificado colocando a cadeia de caracteres entre aspas duplas, conforme ilustrado na [Test6] seção do Arquivo de ifilttst.ini de Exemplo.

Se as entradas Flags e cAttributes não forem especificadas, elas usarão como padrão 0. Se você definir cAttributes igual a 2, deverá especificar dois nomes aAttributes . [Test5] Na seção do exemplo, cAttributes é 1, mas nenhum aAttributes foi especificado. Em seguida, o teste chama o método IFilter::Init com cAttributes igual a 1 e aAttributes igual a NULL. Esse é um caso de teste útil porque é provável que cause uma violação de acesso no método IFilter::Init .

Se ifilttst.exe não conseguir encontrar um arquivo chamado ifilttst.ini no diretório de trabalho, uma configuração padrão será usada para inicializar o objeto IFilter::Init . O exemplo a seguir ilustra a configuração padrão.

[default]
            grfFlags = IFILTER_INIT_APPLY_INDEX_ATTRIBUTES
            cAttributes = 0

Arquivo de ifilttst.ini de exemplo

O arquivo ifilttst.ini é organizado em seções, com o nome da seção entre colchetes. No exemplo, as seções são denominadas [Test1], [Test2]e assim por diante. Todos os nomes de seção devem ser exclusivos. O teste lê os valores da primeira seção e inicializa o IFilter com esses valores. Em seguida, todos os testes são executados usando essa configuração de IFilter . Em seguida, o IFilter é liberado e reinicializado, usando parâmetros listados acima. O processo é repetido até que todas as configurações sejam testadas.

; 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"

Procedimento de teste do IFilter

Depois que o IFilter for inicializado, o programa ifilttst.exe realizará uma série de testes no IFilter. Além de seguir os procedimentos de teste do IFilter , verifique se a implementação do IFilter emprega práticas de código seguras. Confira "Práticas de código seguro para a Pesquisa do Windows" em Implementando manipuladores de filtro na Pesquisa do Windows.

Teste de validação

O teste de validação percorre o objeto uma parte de cada vez, verificando cada parte individual e todos os códigos de retorno. O teste de validação salva todas as estruturas de STAT_CHUNK retornadas em uma lista.

O teste de validação verifica as seguintes condições:

  • O STAT_CHUNK. IDs de parte do idChunk devem ser exclusivas e crescentes.
  • O STAT_CHUNK. O parâmetro flags é um estado de parte reconhecido, como CHUNKSTATE, CHUNK_TEXT ou constantes CenabledHUNK_VALUE.
  • O STAT_CHUNK. O parâmetro breakType é um tipo de interrupção reconhecido (0, 1, 2, 3, 4).
  • Se os atributos de inicialização IFilter especificarem que o IFilter deve retornar apenas partes contendo propriedades internas de tipo de valor, idChunkSource deverá ser igual a 0.
  • Se a parte não for derivada, ou seja, se não for uma propriedade de tipo de valor interno, STAT_CHUNK. idChunkSource deve ser igual a STAT_CHUNK. idChunk.
  • IFilter::GetChunk retorna S_OK ou outro valor retornado aceitável, como FILTER_E_END_OF_CHUNKS, FILTER_E_LINK_UNAVAILABLE e assim por diante.
  • Se a parte contiver texto, IFilter::GetText retornará S_OK, FILTER_S_LAST_TEXT ou FILTER_E_NO_MORE_TEXT.
  • Se IFilter::GetText retornar FILTER_S_LAST_TEXT, a próxima chamada para IFilter::GetText retornará FILTER_E_NO_MORE_TEXT.
  • Se a parte contiver um valor, IFilter::GetValue retornará S_OK ou FILTER_E_NO_MORE_VALUES.

Teste de consistência

O programa ifilttxt.exe inicializa novamente a interface IFilter com os mesmos parâmetros que no teste de validação e executa um teste de consistência. Se a implementação de IFilter tiver sido inicializada com o sinalizador IFILTER_INIT IFILTER_INIT_INDEXING_ONLY, o teste liberará a interface IFilter e a associará novamente antes de fazer outra chamada ao método IFilter::Init .

O teste de consistência verifica as seguintes condições:

  • Cada estrutura STAT_CHUNK retornada pelo método IFilter::GetChunk é idêntica à STAT_CHUNK correspondente retornada no teste de validação.
  • IFilter::GetChunk retorna S_OK ou outro valor retornado aceitável, como FILTER_E_END_OF_CHUNKS, FILTER_E_LINK_UNAVAILABLE e assim por diante.

Teste de entrada inválido

O programa ifilttst.exe inicializa novamente a interface IFilter com os mesmos parâmetros e executa um teste de entrada inválido. Esse teste percorre o documento uma parte de cada vez fazendo chamadas de função incorretamente, como chamar o método IFilter::GetValue quando o chuck atual contiver texto. O teste verifica todos os códigos de retorno quanto à conformidade com a especificação IFilter .

O teste de entrada inválido verifica as seguintes condições:

  • Se a parte atual contiver texto, IFilter::GetValue retornará FILTER_E_NO_VALUES e uma chamada para IFilter::GetText terá êxito.
  • Se a parte atual contiver um valor, IFilter::GetText retornará FILTER_E_NO_TEXT e uma chamada para IFilter::GetValue terá êxito.
  • Se a chamada anterior para IFilter::GetText retornar FILTER_E_NO_MORE_TEXT, chamadas sucessivas para IFilter::GetText retornarão FILTER_E_NO_MORE_TEXT.
  • Se a chamada anterior para IFilter::GetValue retornar FILTER_E_NO_MORE_VALUES, chamadas sucessivas para IFilter::GetValue retornarão FILTER_E_NO_MORE_VALUES.
  • Se a chamada anterior para IFilter::GetChunk retornar FILTER_E_END_OF_CHUNKS, chamadas sucessivas para IFilter::GetChunk retornarão FILTER_E_END_OF_CHUNKS.

Observação

O teste de entrada inválido compara as estruturas de partes atuais com aquelas retornadas no teste de validação para garantir que elas sejam idênticas.

Testando diferentes configurações de IFilter

O programa ifilttst.exe libera a interface IFilter e reassocia, desta vez inicializando-a com o próximo conjunto de parâmetros. O teste repete o ciclo: teste de validação, teste de consistência e teste de entrada inválido, até que todas as configurações de IFilter desejadas especificadas em ifilttst.ini arquivo tenham sido testadas.

Garantindo que os itens registrados sejam indexados

O teste final do IFilter garante que o IFilter esteja registrado corretamente e que ele seja invocado para indexar os itens que você registrou para usá-lo. Você pode usar o Gerenciador de Catálogos para iniciar a reindexação ou usar o Gerenciador de Escopo de Rastreamento (CSM) para configurar regras padrão que indicam as URLs que você deseja que o indexador rastreie. Após a conclusão da indexação, use a interface do usuário do Windows Search para pesquisar uma cadeia de caracteres no conteúdo ou nas propriedades dos itens. Se os itens foram indexados, eles aparecerão nos resultados da pesquisa.

Para obter mais informações sobre a reindexação, consulte Usando o Gerenciador de Catálogos e Usando o Gerenciador de Escopo de Rastreamento. O exemplo de código ReindexMatchingUrls demonstra maneiras de especificar quais arquivos indexar novamente e como. O exemplo de código CrawlScopeCommandLine demonstra como definir opções de linha de comando para operações de indexação do Gerenciador de Escopo de Rastreamento (CSM). Ambos os exemplos de código estão disponíveis no GitHub.

Arquivo de log de exemplo

Mediante solicitação, o programa Ifilttst.exe pode produzir um log que contém uma descrição das etapas que ele executa durante a execução. Os exemplos a seguir são trechos de um arquivo de log, com o detalhamento definido como o valor 3 mais alto possível.

            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.

A primeira linha é uma mensagem informativa, indicando que uma nova configuração foi carregada do arquivo ifilttst.ini. A linha (3) indica o nome da seção no arquivo ifilttst.ini do qual a configuração atual foi lida. As linhas (4) a (7) listam os parâmetros para IFilter::Init. As linhas que começam com INFO são mensagens informativas sobre a associação do IFilter e o início do teste de validação. As linhas que começam com PASS são mensagens sobre testes específicos que foram aprovados.

A linha no exemplo de log a seguir é um aviso. Avisos chamam a atenção para o comportamento IFilter que é problemático, embora legal. Esse aviso indica que o método IFilter::GetChunk retornou uma parte de texto que não contém texto.

WARNING-First call to GetText() returned FILTER_E_NO_MORE_TEXT.

A mensagem de erro de exemplo a seguir indica que o IFilter emitiu uma parte que não foi solicitada.

            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

No caso desta mensagem de erro de exemplo, o IFilter emitiu uma parte com um PID de 0x5. A inspeção da seção [Test1] no ifilttst.ini mostraria que o IFilter foi configurado para não emitir partes com esse PID. Por exemplo, se nem IFILTER_INIT_APPLY_INDEX_ATTRIBUTES nem IFILTER_INIT_APPLY_OTHER_ATTRIBUTES foram especificados na entrada Flags e se cAttributes fossem 0, iFilter emitiria apenas partes com um PID de 0x13 e correspondentes a PID_STG_CONTENTS.

Arquivo de despejo de exemplo

Mediante solicitação, o programa de Ifilttst.exe pode produzir um despejo contendo as partes encontradas e seu conteúdo. O exemplo a seguir é um trecho desse arquivo de despejo.

                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

As nove primeiras linhas descrevem a estrutura da parte atual. O GUID e o PID correspondem a PSGUID_STORAGE/PID_STG_CONTENTS. Esta é uma parte que contém texto sem formatação. O texto está na seguinte estrutura de partes:

10. This is an HTML IFilter test page

A próxima parte, começando na linha 11, tem um GUID diferente, correspondente ao HTML IFiltere a um PID diferente, correspondente a um HREF HTML. Essa é uma propriedade de tipo de valor interno, exportada pelo HTML IFilter.

A próxima parte, começando na linha 21, tem o mesmo GUID e PID, mas seu estado de parte é VALUE em vez de TEXT. Observe que o texto nessas duas últimas partes é o mesmo da primeira parte. Mas como o IFilter foi projetado para três atributos (texto sem formatação, HREF HTML como texto e HREF HTML como um valor) a serem aplicados a essa frase, os resultados são emitidos em três partes separadas.

Recursos adicionais

Desenvolvendo manipuladores de filtro

Sobre manipuladores de filtro na Pesquisa do Windows

Práticas recomendadas para criar manipuladores de filtro no Windows Search

Retornando propriedades de um manipulador de filtro

Filtrar manipuladores que enviam com o Windows

Implementando manipuladores de filtro na Pesquisa do Windows

Registrando manipuladores de filtro