Vista/XPのプロパティシステムで使えるプロパティ
Windows VistaやXP SP2では、Windows Searchをはじめとする各種アプリケーションで、共通のプロパティシステムがある。このシステムには、IPropertySystem経由でアクセスできる。また、XMLベースのProperty Description Schemaを利用すれば、プログラマが自由に拡張することも出来る。
これらのプロパティは、通常、GUID+PIDの組み合わせで判別され、それとは別にCanonical Name(正規名)とDisplay Name(表示名)を持っている。たとえば、
GUID/PID | Canonical Name | Display Name |
---|---|---|
{F29F85E0-4FF9-1068-AB91-08002B27B3D9},2 | System.Title | タイトル |
となっている。また、Canonical NameとGUID/PIDは相互に変換可能(PSGetNameFromPropertyKeyや、PSGetPropertyKeyFromName)なので、どちらか片方が分かれば、プロパティを識別することは可能だ。ただし、Canonical Nameはない場合もある。
下記のプログラムはこのプロパティ一覧を取得するプログラム。
// enumproptypes.cpp #include <windows.h> #include <initguid.h> #include <propsys.h> #include <stdio.h> #include <string.h> #include <locale.h> #include <stdexcept> #include "atlbase.h" #include "atlcom.h" #include "atlstr.h" #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 GetVTStr(VARTYPE vt) { #define VTDEF_ENTRY(a) {#a, a}, static const struct VTDEF {const char* name; VARTYPE vt;} tbl[] = { VTDEF_ENTRY(VT_NULL) VTDEF_ENTRY(VT_LPWSTR) VTDEF_ENTRY(VT_BOOL) VTDEF_ENTRY(VT_UI1) VTDEF_ENTRY(VT_I2) VTDEF_ENTRY(VT_UI2) VTDEF_ENTRY(VT_I4) VTDEF_ENTRY(VT_UI4) VTDEF_ENTRY(VT_I8) VTDEF_ENTRY(VT_UI8) VTDEF_ENTRY(VT_R8) VTDEF_ENTRY(VT_FILETIME) VTDEF_ENTRY(VT_CLSID) VTDEF_ENTRY(VT_BLOB) VTDEF_ENTRY(VT_UNKNOWN) VTDEF_ENTRY(VT_STREAM) {NULL, 0}}; #undef VTDEF_ENTRY for(size_t i = 0; tbl[i].name != NULL; i++) if(tbl[i].vt == vt) return tbl[i].name; CStringW ret; ret.Format(L"%u", vt); return ret; } static size_t GetLevel(LPCWSTR propName) { size_t lev = 0; while(propName = wcschr(propName, '.')) { propName++; lev++; } return lev; } int wmain(int argc, wchar_t* argv[]) { setlocale(LC_ALL, ""); CoInitialize(NULL); try { CComPtr<IPropertySystem> propSys; TOF(propSys.CoCreateInstance(CLSID_PropertySystem)); CComPtr<IPropertyDescriptionList> pdl; TOF(propSys->EnumeratePropertyDescriptions( PDEF_ALL, __uuidof(IPropertyDescriptionList), (void**)&pdl)); UINT count = 0; TOF(pdl->GetCount(&count)); for(UINT i = 0; i < count; i++) { CComPtr<IPropertyDescription> pd; if(FAILED(pdl->GetAt(i, IID_IPropertyDescription, (void**)&pd))) continue; VARTYPE type = VT_NULL; if(FAILED(pd->GetPropertyType(&type))) continue; LPWSTR cname = NULL; pd->GetCanonicalName(&cname); if(GetLevel(cname) == 1) { PROPERTYKEY key; pd->GetPropertyKey(&key); LPWSTR clsid; StringFromCLSID(key.fmtid, &clsid); LPWSTR dname = NULL; pd->GetDisplayName(&dname); wprintf(L"%s,%u\t%s\t%s\t%s\n", clsid, key.pid, cname, dname, GetVTStr(type)); CoTaskMemFree(dname); CoTaskMemFree(clsid); } CoTaskMemFree(cname); } } catch(std::exception& e) { fprintf(stderr, "%s\n", e.what()); } CoUninitialize(); return 0; }