Choosing your property API

It is time that I talk a little about what to do if you want your application to run on XP. There are three sets of APIs, each with subtle differences and caveats, and ultimately your choice requires deciding what platform your application must run on:

Windows Vista:

Call IShellItem2::GetPropertyStore to get an IPropertyStore interface. The output property store includes property handler properties (e.g. Photo dimensions) and innate properties (e.g. Size, Name). This is your one-stop-shop for properties.

Caveat: This technique only works on Vista and later OSes.

Windows XP with Windows Desktop Search 3.x:

You can pass an IShellItem interface to PSGetItemPropertyHandler to get an IPropertyStore interface. Much of the property system works with Windows Desktop Search 3.x, so you can ask for property descriptions and everything. One upshot is that this API works identically on Vista so if you are able to choose to use it, you don't have to detect versions or anything.

Unfortunately, innate properties are only available through methods on IShellFolder and IShellFolder2. So you're on your own for those.

Caveat: Properties written to this API may or may not readable on Vista. [Aside: The full story is more complicated, but I'd like to move on for now] Innate properties like PKEY_Size are not exposed.

Windows XP; Windows XP with Windows Desktop Search 2.x:

Properties on XP are exposed through IPropertySetStorage. The supported technique is to call IShellFolder::BindToStorage(IPropertySetStorage) for the item. 

Innate properties such as size and name are exposed through various methods on IShellFolder and IShellFolder2.

Caveats: Properties written with this API may or may not be readable on Vista. Furthermore, on Vista, this technique only works for some namespaces and not others. 

Gotcha: Many people mistakenly call StgOpenStorageEx. Don't do that! StgOpenStorageEx is only supported for specific formats like OLE Compound Documents or NTFS secondary stream storage. StgOpenStorageEx doesn't know how to read the EXIF header from a .JPG image. IShellFolder::BindToStorage knows how to do such things.

Best of all worlds:

If you really enjoy coding, you can detect if a given API is present by calling GetProcAddress or QueryInterface [Aside: please don't detect versions... just directly test if the API is present or not], select the best available API, and deliver an application that works better on Vista. Hey, "Works better on Vista" sounds like a marketing slogan -- you could have fun coding and sell more software too!

-Ben Karas