4

The Windows Shell's property system defines a standard property called System.Video.FrameRate (documented here), which is available on most video files. The surrounding documentation only covers unmanaged APIs for getting these values.

How do I access this Windows Property in C#?

Ben
  • 51,770
  • 36
  • 127
  • 149
Matias
  • 541
  • 5
  • 22
  • This question is currently on hold as "off-topic". I've clarified it, and I think it should now be clear that this is definitely "about programming" as defined in the help centre - it meets the "a specific programming problem" and "practical, answerable problems that are unique to the programming profession" criteria. And if the OP didn't "demonstrate...understanding" I believe the edit addresses that. – Ian Griffiths Jul 25 '13 at 15:23
  • Thanks for editing the question, and for the answer. – Matias Jul 25 '13 at 17:29

1 Answers1

4

To access a shell property (and that's what this is - these 'Windows' properties are just shell properties predefined by Windows, as distinct from application-specific properties) there are two usual ways to do this: interop, or the Windows API code pack.

The Windows API Code Pack is likely to be the easiest way to do this. To obtain this property, first you need to determine which shell object you'd like to use. (Properties are always found on some particular objects. So this property is not some global value telling you the system frame rate - it is typically present on video files, and it tells you the frame rate of that file.) This code gets the shell object for a video I happen to have on my system, retrieves the property and displays its value.

ShellObject obj = ShellObject.FromParsingName(@"D:\Video\IanAndDeborahTree.mp4");
ShellProperty<uint?> rateProp = obj.Properties.GetProperty<uint?>("System.Video.FrameRate");
Debug.WriteLine("{0:G3}FPS", rateProp.Value/1000.0);

Note that the property's value is a nullable unsigned int. If you ask for a property of type int, it'll fail, indicating that no such property is available. So you have to go for uint?. You should really also check whether the property was actually present - I'm not bothering here because I know it will be.

The other approach would be to use interop to talk directly to the shell API (which is what the API code pack does for you). That's a lot of work though - the number of hoops you'd have to jump through to achieve what these three lines do is massive, because you end up needing to define a surprisingly large number of COM interfaces in a form that .NET interop can handle.

Ian Griffiths
  • 14,302
  • 2
  • 64
  • 88
  • Thanks for the answer Ian, which reference should I add to the project? Which libraries should I use? Thanks – Matias Jul 24 '13 at 18:40
  • I am having this error The type 'Microsoft.WindowsAPICodePack.Shell.PropertySystem.PropertyKey' is defined in an assembly that is not being referenced. You must add a reference to the assembly 'Microsoft.WindowsAPICodePack, Version=1.1.0.0, Culture=neutral, PublicKeyToken=null'. – Matias Jul 24 '13 at 21:36
  • You'll need to add a reference to two DLLs: the main codepack assembly `Microsoft.WindowsAPICodePack.dll` and also the shell assembly `Microsoft.WindowsAPICodePack.Shell.dll`. – Ian Griffiths Jul 25 '13 at 06:53
  • Now is working fine, thanks. I have to use Microsoft.WindowsAPICodePack, using Microsoft.WindowsAPICodePack.Shell and using Microsoft.WindowsAPICodePack.Shell.PropertySystem. Now, do you know which is the property to get the duration (in seconds) of the video. Thanks – Matias Jul 25 '13 at 18:20
  • I don't know, but about 30 seconds of digging around in the docs lead me to `System.Media.Duration` which sounds like it probably does what you want - http://msdn.microsoft.com/en-us/library/windows/desktop/bb787399(v=vs.85).aspx - try that and let us know if it works! – Ian Griffiths Jul 26 '13 at 07:48
  • It worked, but the result is ulong?. For example, in my case, it returns 89808799999 when the real duration of the video is 8980,8799999 – Matias Jul 26 '13 at 13:35
  • From the very first paragraph in the documentation for the property at http://msdn.microsoft.com/library/windows/desktop/bb787399 we learn that this setting "is measured in 100ns units, not milliseconds." So the result you are seeing is exactly what you would expect. – Ian Griffiths Jul 30 '13 at 07:39
  • Hi again, I am having problems with this solution when installing the application which uses ShellObject.FromParsingName on Windows XP. Do you know what should I do to enable this function on Windows XP? Thanks again – Matias Sep 19 '13 at 20:13
  • It might not actually be available on XP. One of the things that changed in Vista was that they introduced a load of new functionality to the shell's property system. I don't know for certain but it wouldn't be at all surprising if XP simply can't provide this info. What happens if you bring up the properties on the file in question in Explorer in XP? Is there a way if seeing the properties you want in the Explorer UI? If not, then it almost certainly isn't available through the API either. – Ian Griffiths Nov 07 '13 at 16:42