Where are the WPD property keys in C#?


If you followed the exercise from our first C# post, you must have noticed that the PortableDeviceApi and PortableDeviceTypes typelibs don’t expose the WPD property keys such as WPD_OBJECT_ID, WPD_OBJECT_FORMAT, etc. This can be a major blocker since for starters, we need to specify a basic set of client information properties to open a connection to the device.

If you used C++, the WPD property keys definitions could be brought in by linking against PortableDeviceGuids.lib. Linking against a C lib is not an option for a C# application. It’s not even possible to generate a typelib for a C lib. The only option is to manually define each of the property keys all over again in your C# application.

The C++ PROPERTYKEY data type maps to the PortableDeviceApiLib._tagpropertykey interop data type. We can look up the PROPERTYKEY declaration in PortableDevice.h and use that to generate an equivalent C# property key object.

Let’s take a look at WPD_OBJECT_ID – the C++ definition (from PortableDevice.h) is:

// 
// WPD_OBJECT_ID 
//   [ VT_LPWSTR ] Uniquely identifies object on the Portable Device. 
DEFINE_PROPERTYKEY( WPD_OBJECT_ID , 0xEF6B490D, 0x5CD8, 0x437A, 0xAF, 0xFC, 0xDA, 0x8B, 0x60, 0xEE, 0x4A, 0x3C , 2 ); 


Mapping this to C# would result in something like:

class PortableDevicePKeys
{
    static PortableDevicePKeys()
    {
        WPD_OBJECT_ID.fmtid = new Guid(0xEF6B490D, 0x5CD8, 0x437A, 0xAF, 0xFC, 0xDA, 0x8B, 0x60, 0xEE, 0x4A, 0x3C);
        WPD_OBJECT_ID.pid = 2;
    }

    public static PortableDeviceApiLib._tagpropertykey WPD_OBJECT_ID;
}

We can then reference the property as PortableDevicePKeys.WPD_OBJECT_ID whenever required.

Making life easier

Since defining each of these property keys by hand may cause severe RSI, here’s a little script that will generate the definitions for you given PortableDevice.h. In addition to generating the property keys, it will also generate the GUID definitions (such as for WPD_FUNCTIONAL_CATEGORY_STORAGE, WPD_OBJECT_FORMAT_WMA, etc.)

Copy the script from the text-box above, paste it into Notepad and save it as gencsinc.js. Copy PortableDevice.h to the same folder as gencsinc.js and then run gencsinc.js using “cscript gencsinc.js“. This will generate a PortableDeviceConstants.cs file which you may add to your C# project.

Once the generated file is added to your project, add “using PortableDeviceConstants;” to your target C# source. To reference property keys, you can simply use PortableDevicePKeys.propertyname (e.g. PortableDevicePKeys.WPD_OBJECT_ID) and to reference GUIDs, you can simply use PortableDeviceGuids.guidname (e.g. PortableDeviceGuids.WPD_OBJECT_FORMAT_WMA).

Comments (4)

  1. dimeby8 says:

    Since setting a WPD property requires manipulating a PROPVARIANT structure through interop, we must make

  2. This article was written for application developers who are interested in displaying portable device

  3. This article was written for application developers who are interested in displaying portable device

  4. m says:

    thanx tons for your special blog'

    but howdo i get the

    PortableDevice.h ?????????????