Click here to Skip to main content
6,822,123 members and growing! (17,801 online)
Email Password   helpLost your password?
    Intermediate License: The Code Project Open License (CPOL)

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

By Williarob

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:   Ev
C# (C#3.0), Windows (Win7), .NET (.NET3.5), Win32, Win64, Visual-Studio (VS2008), Dev
Revision:2 (See All)
Posted:23 Oct 2009
Updated:26 Oct 2009
Views:3,208
Bookmarked:11 times
Technical Blog
printPrint   add Share
      Discuss Discuss   Broken Article?Report  
0 votes for this technical blog
A Technical Blog article. View entire blog here.

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"):

        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 propeties 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:

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:

ConsoleApplication1.zip (218.76 kb) 

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:

        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)

About the Author

Williarob


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

Other popular Audio and Video articles:

Article Top
You must Sign In to use this message board.
FAQ FAQ 
 
Noise Tolerance  Layout  Per page   
 Msgs 1 to 2 of 2 (Total in Forum: 2) (Refresh)FirstPrevNext
GeneralJust curious PinmemberJohnny J.23:46 23 Oct '09  
GeneralRe: Just curious PinassociateWilliarob7:15 26 Oct '09  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

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

PermaLink | Privacy | Terms of Use
Last Updated: 26 Oct 2009
Editor:
Copyright 2009 by Williarob
Everything else Copyright © CodeProject, 1999-2010
Web22 | Advertise on the Code Project