2016-06-04 17 views
0

Я использую IFilter для индексирования некоторых документов MS Office. загрузка из файла в порядке, все работает отлично, как и во всех руководствах и образцов:Initiliaze IFilter от IStream

HRESULT hr_f = LoadIFilter(filename, 0, (void **)&pFilter);

Однако, используя BindIFilterFromStream API не удалось, и я не могу понять, как правильно его использовать.

HRESULT hr_ss = BindIFilterFromStream(spStream/*my IStream* impl*/, 0, (void **)&pFilter);

я реализовал интерфейс IStream, только метод (за исключением IUnknown «S) Вызванный во время инициализации является:

HRESULT StreamFilter::Stat(STATSTG * pstatstg, DWORD grfStatFlag) 
{ 
    //Microsoft Office Ifilter from Windows Registry 
    const IID CLSID_IFilter = { 
     0xf07f3920, 
     0x7b8c, 
     0x11cf, 
     { 0x9b, 0xe8, 0x00, 0xaa, 0x00, 0x4b, 0x99, 0x86 } 

     //{f07f3920-7b8c-11cf-9be8-00aa004b9986} 
    }; 
    LARGE_INTEGER pSize; 
    int fl = GetFileSizeEx(_hFile, &pSize); 
    memset(pstatstg, 0, sizeof(STATSTG)); 
    pstatstg->clsid = CLSID_IFilter; 
    pstatstg->type = STGTY_STREAM; 
    pstatstg->cbSize.QuadPart = pSize.QuadPart; 

    return S_OK; 
} 

После этого hr_ss является E_FAIL и IFilter является NULL.

Есть случай Using IFilter in C#, и те, метод прекрасно работает только для * .pdf в с ++ тоже, но не для MSO документы ...

+0

Из вашей ссылки для BindIFilterFromStream: «Служба индексирования не поддерживается как Windows XP» - в какой версии Windows вы пытаетесь это сделать? –

+0

hm, devmachine - это windows 8.1, я тестировал в win2k3 - тот же результат, что и на моем Win8 PC ... \t Кажется, я осознал свою ошибку :(Это значит, что в Windows, новее, чем WinXP, я не могу использовать этот API? Прошу прощения за мой английский ... – tomato

ответ

0

Я понял, как инициализировать IFilter правильно, вот код:

HRESULT hr = LoadIFilter(L".doc", 0, (void **)&pFilter); 
IPersistStream *stream; 
HRESULT hr_qi = pFilter->QueryInterface(&stream); 

std::ifstream ifs(filename, ios::binary); 
std::string content((std::istreambuf_iterator<char>(ifs)), 
    (std::istreambuf_iterator<char>())); 

IStream *comStream; 
HGLOBAL hMem = ::GlobalAlloc(GMEM_MOVEABLE, content.size()); 
LPVOID pDoc = ::GlobalLock(hMem); 
memcpy(pDoc, content.c_str(), content.size()); 
::GlobalUnlock(hMem); 
HRESULT hr_mem = ::CreateStreamOnHGlobal(hMem, true, &comStream); 
HRESULT hr_stream_load = stream->Load(comStream); 

И получать текст из документа, как обычный образец из MSDN

if (SUCCEEDED(hr)) 
{ 
    DWORD flags = 0; 
    HRESULT hr = pFilter->Init(IFILTER_INIT_INDEXING_ONLY | 
          IFILTER_INIT_APPLY_INDEX_ATTRIBUTES | 
          IFILTER_INIT_APPLY_CRAWL_ATTRIBUTES | 
          IFILTER_INIT_FILTER_OWNED_VALUE_OK | 
          IFILTER_INIT_APPLY_OTHER_ATTRIBUTES, 
          0, 0, &flags); 
    if (FAILED(hr)) 
    { 
    pFilter->Release(); 
    throw exception("IFilter::Init() failed"); 
    } 

    Start(); 

    STAT_CHUNK stat; 
    while (SUCCEEDED(hr = pFilter->GetChunk(&stat))) 
    { 
    if ((stat.flags & CHUNK_TEXT) != 0) 
     ProcessTextChunk(pFilter, stat); 

    if ((stat.flags & CHUNK_VALUE) != 0) 
     ProcessValueChunk(pFilter, stat); 
    } 

    Finish(); 

    pFilter->Release();  
} 
else 
{ 
    throw exception("LoadIFilter() failed"); 
} 

Вам не нужно реализовать свой собственный Istre am, просто инициализируйте его из вашего буфера ...