Click here to Skip to main content
15,867,568 members
Articles / Desktop Programming / Win32

How to get the length (duration) of a media File in C# on Windows 7

Rate me:
Please Sign up or sign in to vote.
4.50/5 (6 votes)
26 Oct 2009CPOL2 min read 113.6K   26   9
If you have ever looked at a media file (audio or video) in explorer on a Windows 7 PC, you may have noticed that it displays additional information about that media file that previous versions of Windows didn't seem to have access to, for example the length/duration of a Quicktime Movie Clip.

If you have ever looked at a media file (audio or video) in the explorer window on a Windows 7 PC, you may have noticed that it displays additional information about that media file that previous versions of Windows didn't seem to have access to, for example the length/duration of a Quicktime Movie Clip:

Even right clicking the file and choosing Properties > Details does not give me this information on my Vista Ultimate PC. Of course, now that Windows has the ability to fetch this information, so do we as developers, through the Windows API (The DLL to Import by the way is "propsys.dll"):

C#
internal enum PROPDESC_RELATIVEDESCRIPTION_TYPE
{
            PDRDT_GENERAL,
            PDRDT_DATE,
            PDRDT_SIZE,
            PDRDT_COUNT,
            PDRDT_REVISION,
            PDRDT_LENGTH,
            PDRDT_DURATION,
            PDRDT_SPEED,
            PDRDT_RATE,
            PDRDT_RATING,
            PDRDT_PRIORITY
}

       [DllImport("propsys.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        internal static extern int PSGetNameFromPropertyKey(
            ref PropertyKey propkey,
            [Out, MarshalAs(UnmanagedType.LPWStr)] out string ppszCanonicalName
        );
 
        [DllImport("propsys.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        internal static extern HRESULT PSGetPropertyDescription(
            ref PropertyKey propkey,
            ref Guid riid,
            [Out, MarshalAs(UnmanagedType.Interface)] out IPropertyDescription ppv
        );
 
        [DllImport("propsys.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        internal static extern int PSGetPropertyKeyFromName(
            [In, MarshalAs(UnmanagedType.LPWStr)] string pszCanonicalName,
            out PropertyKey propkey
        );

However, before you rush off to play with these, you may be interested to know that Microsoft has created a great Library that showcases this and many of the other new API features of Windows 7. It's called the WindowsAPICodePack and you can get it here.

If you open the WindowsAPICodePack Solution and compile the Shell Project, it creates a nice wrapper around all the neat new system properties available through propsys.dll. Adding a reference to WindowsAPICodePack.dll and WindowsAPICodePack.Shell.dll to a console application will allow you to get the duration of just about any media file that Windows recognizes. (Of course the more codec packs you install, the more types it will recognize, I recommend The Combined Community Codec Pack to maximize your range of playable files.)

Here is a simple example showing how to get the duration of a media file in C# using this library:

C#
namespace ConsoleApplication1
{
    using System;
 
    using Microsoft.WindowsAPICodePack.Shell;
 
    class Program
    {
        static void Main(string[] args)
        {
            if(args.Length < 1)
            {
                Console.WriteLine("Usage: ConsoleApplication1.exe [Filename to test]");
                return;
            }
 
            string file = args[0];
            ShellFile so = ShellFile.FromFilePath(file);
            double nanoseconds;
            double.TryParse(so.Properties.System.Media.Duration.Value.ToString(), 
			out nanoseconds);
            Console.WriteLine("NanaoSeconds: {0}", nanoseconds);
            if (nanoseconds > 0)
            {
                double seconds = Convert100NanosecondsToMilliseconds(nanoseconds) / 1000;
                Console.WriteLine(seconds.ToString());
            }
        }
 
        public static double Convert100NanosecondsToMilliseconds(double nanoseconds)
        {
            // One million nanoseconds in 1 millisecond, 
            // but we are passing in 100ns units...
            return nanoseconds * 0.0001;
        }
    }
} 

As you can see, the System.Media.Duration Property returns a value in 100ns units so some simple math will turn it into seconds. Download the Test Project which includes the prebuilt WindowsAPICodePack.dll and WindowsAPICodePack.Shell.dll files in the bin folder:

For the curious, I tested this on Windows XP and as you'd expect, it didn't work:

Unhandled Exception: System.DllNotFoundException: Unable to load DLL 'propsys.dll': 
The specified module could not be found. (Exception from HRESULT: 0x8007007E)

On Vista Ultimate SP2, it still didn't work - nanoseconds was always 0, though it didn't throw any exceptions.

For the older systems, I guess we are limited to using the old MCI (Media Control Interface) API:

C#
using System.Runtime.InteropServices;
 
        [DllImport("winmm.dll")]
        public static extern int mciSendString(string lpstrCommand, 
	StringBuilder lpstrReturnString, int uReturnLength, int hwndCallback);
        [DllImport("winmm.dll")]
        private static extern int mciGetErrorString(int l1, StringBuilder s1, int l2);
 
        private void FindLength(string file)
        {
            string cmd = "open " + file + " alias voice1";
            StringBuilder mssg = new StringBuilder(255);
            int h = mciSendString(cmd, null, 0, 0);
            int i = mciSendString("set voice1 time format ms", null, 0, 0);
            int j = mciSendString("status voice1 length", mssg, mssg.Capacity, 0);
            Console.WriteLine(mssg.ToString());
        }

Which works fine for .mp3 and .avi and other formats that play natively in Windows Media Player, but even with a codec pack installed, it doesn't work on Quicktime or .mp4 files, where the new Windows 7 API did.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Salem Web Network
United States United States
Robert Williams has been programming web sites since 1996 and employed as .NET developer since its release in 2002.

Comments and Discussions

 
QuestionWindowsAPICodePack doesn't work on servers? Pin
William Campbell2-Jun-15 7:00
William Campbell2-Jun-15 7:00 
AnswerRe: WindowsAPICodePack doesn't work on servers? Pin
Pouriya Ghasemi26-Jul-16 10:33
Pouriya Ghasemi26-Jul-16 10:33 
SuggestionmciSendString needs to send a Close Pin
William Campbell2-Jun-15 6:57
William Campbell2-Jun-15 6:57 
Questiona problem with prosys.dll Pin
ali327115-May-12 1:34
ali327115-May-12 1:34 
QuestionTimenspan Pin
ttxman28-Nov-11 23:24
ttxman28-Nov-11 23:24 
GeneralWorks on Vista Pin
reklats7-May-10 10:19
reklats7-May-10 10:19 
GeneralNice and simple Pin
Michael900014-Mar-10 10:38
Michael900014-Mar-10 10:38 
GeneralJust curious Pin
Johnny J.23-Oct-09 22:46
professionalJohnny J.23-Oct-09 22:46 
GeneralRe: Just curious Pin
Williarob26-Oct-09 6:15
Williarob26-Oct-09 6:15 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.