ファイルに関連づけられたプロパティ

また、ファイルなどに対して関連づけられたプロパティは、IShellItem2::GetPropertyStoreで取得できる。

下記のコードは、ファイルに関連づけられたプロパティ一覧を表示する物。

// listprops.cpp
#include <windows.h>
#include <initguid.h>
#include <propsys.h>
#include <propvarutil.h>
#include <shobjidl.h>
#include <stdio.h>
#include <string.h>
#include <locale.h>
#include <stdexcept>

#include "atlbase.h"
#include "atlcom.h"
#include "atlstr.h"

#pragma comment(lib, "propsys.lib")

#define TOF(expr) do {HRESULT hr = expr; if(FAILED(hr)) {CStringA s; s.Format("%s(%d): HR=0x%08X: %s", __FILE__, __LINE__, hr, #expr); throw std::runtime_error((const char*)s);}} while(0)

static CStringW getKeyFromPROPERTYKEY(REFPROPERTYKEY key)
{
  CStringW keyStr;
  PWSTR name = NULL;
  if(SUCCEEDED(PSGetNameFromPropertyKey(key, &name)))
  {
    keyStr = name;
  }
  else
  {
    StringFromCLSID(key.fmtid, &name);
    keyStr.Format(L"%s,%u", name, key.pid);
  }
  if(name)
    CoTaskMemFree(name);
  return keyStr;
}

int wmain(int argc, wchar_t* argv[])
{
  if(argc != 2)
  {
    printf("props FILENAME\n");
    return 0;
  }
  
  setlocale(LC_ALL, "");
  CoInitialize(NULL);
  
  try
  {
    CComPtr<IShellItem2> si2;
    TOF(SHCreateItemFromParsingName(
      argv[1], NULL, __uuidof(IShellItem2), (void**)&si2));
    
    CComPtr<IPropertyStore> ps;
    TOF(si2->GetPropertyStore(
      GPS_DEFAULT, __uuidof(IPropertyStore), (void**)&ps));
    
    DWORD count = 0;
    TOF(ps->GetCount(&count));
    for(DWORD i = 0; i < count; i++)
    {
      PROPERTYKEY key;
      if(FAILED(ps->GetAt(i, &key)))
        continue;
      
      CStringW keyName = getKeyFromPROPERTYKEY(key);
      
      PROPVARIANT pv;
      PropVariantInit(&pv);
      if(FAILED(ps->GetValue(key, &pv)))
        continue;
      
      PWSTR pstr = NULL;
      if(SUCCEEDED(PropVariantToStringAlloc(pv, &pstr)) || pstr)
      {
        wprintf(L"%s=\"%s\"\n", keyName, pstr);
        CoTaskMemFree(pstr);
      }
      
      PropVariantClear(&pv);
    }
  }
  catch(std::exception& e)
  {
    fprintf(stderr, "%s\n", e.what());
  }
  CoUninitialize();
  return 0;

}

使い方は、簡単で、

listprops filename.pdf

のように使う。