Saturday, May 23, 2020

The given CanonicalName is not valid ShellObject.Properties.GetProperty Microsoft Windows API Code Pack

If you are getting "The given CanonicalName is not valid" while using Microsoft Windows API Code Pack to get metadata about a image. Look no further, I have been racking my brains, over how to get this to work.

You probably have tried then following attempts that yielded the error. In this example, it's just try to extract MIMEType, a field always populated and chosen for testing purposes.

This first attempt to get MimeType1 method uses the proper string signature to extract the MIMEType property, but you get the "The given CanonicalName is not valid" error. The second attempt also fails.

var MimeType1 = picture.Properties.GetProperty("SystemProperties.System.MIMEType").ToString(); //properly specified
var MimeType2 = picture.Properties.GetProperty("MIMEType"); //random attempt

So what is going on here? 

This method which uses the PropetyKey type and works, and you think you could just get the string of this.


var MimeType1 = picture.Properties.GetProperty(SystemProperties.System.MIMEType).ToString(); //properly specified

But SystemProperties.System.MIMEType has no .CanonicalName property to use, or any named property and toString() will not work.

But it turns out that the documentation for ShellObject.Properties.GetProperty() is very hard to find! I can get valid types here

So you have to look at the source code of the Microsoft Windows API Code Pack

And from there,  you get that GetProperty is really a native win32 call to propsys.dll


        //PS refer to Propery Store - http://www.pinvoke.net/default.aspx/Interfaces/IPropertyStore.html
        [DllImport("propsys.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        internal static extern int PSGetPropertyKeyFromName(
            [In, MarshalAs(UnmanagedType.LPWStr)] string pszCanonicalName,
            out PropertyKey propkey
        );


And at leas there some documentation of this call - https://docs.microsoft.com/en-us/windows/win32/api/propsys/nf-propsys-psgetnamefrompropertykey

From here it gives you a very vague idea of what to do.


Solution:

It turns out that you cannot use what you would naturally think;


"SystemProperties.System.MIMEType" must be "System.MIMEType"
"SystemProperties.System.Photo.CameraModel" must be "System.Photo.CameraModel"

The metadata image, video, music properties are all listed here to extract

https://docs.microsoft.com/en-us/windows/win32/properties/props

You may ask why use the string name, this is the only way to iterate over the collection, see my post here.



No comments:

Post a Comment