получить свойства OLE с помощью IFilter C++

Я использую COM-объект IFilter для извлечения текста из файлов. Мне удалось извлечь значения свойств OLE (например, значение автора, значение компании и т. д.), но я не мог понять, как узнать, какое значение является автором, компанией и т. д.

CoInitialize(NULL);
IFilter *pFilt;
HRESULT hr = LoadIFilter( L"c:\\bla.docx", 0, (void**)&pFilt );
if ( FAILED( hr ) )
{
    cout<<"Bla"<<endl;
}

ULONG flags;
hr = pFilt->Init( IFILTER_INIT_APPLY_INDEX_ATTRIBUTES, 0, 0, &flags );
if ( FAILED( hr ) )
{
    cout<<"Bla"<<endl;
}
if(flags == 1)
{
    cout<<"With OLE!"<<endl;
}
STAT_CHUNK chunk;
while ( SUCCEEDED( hr = pFilt->GetChunk( &chunk ) ) )
{
    if ( CHUNK_TEXT == chunk.flags )
    {
        WCHAR awc[100];
        ULONG cwc = 100;
        while ( SUCCEEDED( hr = pFilt->GetText( &cwc, awc ) ) )
        {
            cout<<awc<<endl;
            // process the text buffer.&nbsp;.&nbsp;.
        }
    }
    else // CHUNK_VALUE
    {
        PROPVARIANT *pVar;
        while ( SUCCEEDED( hr = pFilt->GetValue( &pVar ) ) )
        {

            **// Right here, i can see the value of pVar is the correct author, but i dont know how to tell this is the author, or the company etc..**
            PropVariantClear( pVar );
            CoTaskMemFree( pVar );
        }
    }

}

Другими словами, мне нужно знать идентификатор свойства и сопоставить его со значением свойства.

Я видел решения, использующие IPropertyStorage->ReadMultiple, но я пытаюсь получить то же самое с помощью IFilter.

Большое спасибо! Надеюсь, вы найдете ответ.


person user1612927    schedule 08.08.2014    source источник
comment
Элемент attribute чанка должен вас заинтересовать.   -  person Hans Passant    schedule 08.08.2014


Ответы (1)


Значение определяется в поле STAT_CHUNK's attribute. Он определяется как структура FULLPROPSPEC, которая (в большинстве случаев) может быть напрямую связана с Система свойств Windows.

FULLPROPSPEC может указывать либо на свойство GUID+id, либо на пользовательское свойство, определяемое его именем (в идеале, чтобы определить это, необходимо проверить наличие psProperty.ulKind). Сегодня большая часть реализации просто не использует имя и придерживается определения «свойства» GUID (набор свойств) + PROPID (int).

Так, например, это пример кода, который способен определить, какое имя свойства и значение отформатировано как строка, используя PSGetNameFromPropertyKey и IPPropertyDescription::FormatForDisplay :

...
if (CHUNK_VALUE == chunk.flags)
{
  if (chunk.attribute.psProperty.ulKind == PRSPEC_PROPID)
  {
    // build a Windows Property System property key
    // need propsys.h & propsys.lib
    PROPERTYKEY pk;
    pk.fmtid = chunk.attribute.guidPropSet;
    pk.pid = chunk.attribute.psProperty.propid;
    PWSTR name;
    if (SUCCEEDED(PSGetNameFromPropertyKey(pk, &name)))
    {
      wprintf(L" name:'%s'\n", name);
      CoTaskMemFree(name);
    }

    IPropertyDescription *pd;
    if (SUCCEEDED(PSGetPropertyDescription(pk, IID_PPV_ARGS(&pd))))
    {
      PROPVARIANT *pVar;
      hr = pFilt->GetValue(&pVar);
      if (SUCCEEDED(hr))
      {
        LPWSTR display;
        if (SUCCEEDED(pd->FormatForDisplay(*pVar, PDFF_DEFAULT, &display)))
        {
          wprintf(L" value:'%s'\n", display);
          CoTaskMemFree(display);
        }
        PropVariantClear(pVar);
      }
      pd->Release();
    }

    continue;
  }  // otherwise it's a string

  PROPVARIANT *pVar;
  hr = pFilt->GetValue(&pVar);
  if (SUCCEEDED(hr))
  {
    // do something with the value
    PropVariantClear(pVar);
  }
}
person Simon Mourier    schedule 08.08.2014