Click here to Skip to main content
12,305,151 members (74,996 online)
Click here to Skip to main content
Add your own
alternative version


109 bookmarked

Interoperating with Windows Media Player using P/Invoke and C#

, 7 Feb 2004 CPOL
Rate this:
Please Sign up or sign in to vote.
An article demonstrating the usage of Platform Invoke Services in Visual C# to interoperate with Windows Media Player.


This article hopes to demonstrate:

  • How to use P/Invoke to call unmanaged code.
  • How to use Spy++ to log Windows messages and get wParam and lParam values.
  • How to implement FindWindow() and SendMessage() in C#.
  • How to Interoperate with Windows Media Player.

Introduction to Win32 APIs

MSDN's definition of the Windows API is:

The Windows API (Application Programming Interface) consists of the functions, messages, data structures, data types, and statements you can use in creating applications that run under Microsoft Windows. The parts of the API you use most are code elements for calling API functions from Windows. These include procedure declarations (for the Windows functions), user-defined type definitions (for data structures passed to those functions), and constant declarations (for values passed to and returned from those functions).

In short, Windows APIs are DLLs that are embedded in the Microsoft Windows operating system. The advantage of using Windows APIs in your code is that development time and complexity may be reduced because they contain hundreds of useful functions already written. The disadvantage is that Windows APIs do not use managed code and have data types that are different from those used with Visual Studio .NET. While the .NET framework has wrapped a significant portion of the Win32 API into managed code, the ones that remain unmanaged and without a .NET equivalent may be called by managed code using the platform invoke service.

Introducing Platform Invocation Services

Platform Invocation Services (P/Invoke) is a mechanism by which managed code calls unmanaged functions that are implemented in a DLL.


When calling an unmanaged function, platform invoke must have the DLL file name and function or ordinal number. The DLLImport attribute is used to specify the DLL location that contains the implementation of an external method and its parameters are used to specify specific behavior such as EntryPoint and CharSet. For more information on the syntax of the DllImport attribute, see DllImportAttribute class at MSDN.

Table 1: Commonly used DLLs in the Win32 API


Description of its contents


Low-level operating system functions for memory management and resource handling.


Graphics Device Interface (GDI) functions for device output, such as those for drawing and font management.


Windows management functions for message handling, timers, menus, and communications.

Steps to call Win32 API using C#

  1. Import the System.Runtime.InteropServices namespace.
  2. Define functions by using DLLImport.
  3. Add code to call the Win32 API.

We are going to implement the FindWindow() and SendMessage() related Win32 API functions found in the User32.dll as illustrated in the Win32 class below.

public class Win32
    // The WM_COMMAND message is sent when the user
    // selects a command item from a menu, 
    // when a control sends a notification message
    // to its parent window, or when an 
    // accelerator keystroke is translated.
    public const int WM_COMMAND = 0x111;

    // The FindWindow function retrieves a handle
    // to the top-level window whose class name
    // and window name match the specified strings.
    // This function does not search child windows.
    // This function does not perform a case-sensitive search.
    public static extern int FindWindow(string strClassName, 
                                             string strWindowName);

    // The FindWindowEx function retrieves
    // a handle to a window whose class name 
    // and window name match the specified strings.
    // The function searches child windows, beginning
    // with the one following the specified child window.
    // This function does not perform a case-sensitive search.
    public static extern int FindWindowEx(int hwndParent, 
        int hwndChildAfter, string strClassName, string strWindowName);

    // The SendMessage function sends the specified message to a 
    // window or windows. It calls the window procedure for the specified 
    // window and does not return until the window procedure
    // has processed the message. 
    public static extern Int32 SendMessage(
        int hWnd,               // handle to destination window
        int Msg,                // message
        int wParam,             // first message parameter
        [MarshalAs(UnmanagedType.LPStr)] string lParam); 
                                // second message parameter

    public static extern Int32 SendMessage(
        int hWnd,               // handle to destination window
        int Msg,                // message
        int wParam,             // first message parameter
        int lParam);            // second message parameter

    public Win32()



Windows Media Player Interoperability Conceptual Art

Sample screenshot


  • Microsoft Visual Studio .NET
  • Microsoft Spy++
  • Windows Media Player
  1. Open Spy++ and press the Log Messages button, or press Ctrl + M.
  2. Open Microsoft Windows Media Player and arrange your windows so that Spy++ and Windows Media Player are both visible.
  3. Make sure Windows Media Player is not using the Auto Hide Menu bar feature and drag the Finder Tool to the outer Windows Media Player Window entitled “Windows Media Player”.

- Or -

If you know the handle of the Windows Media Player window, you may type it into the Handle box.


Next, proceed to the Messages tab and clear all selected messages. In the Messages to View list box, scroll down and select WM_COMMAND and click on OK.

At this point, having only WM_COMMAND selected will make the next step much easier.


Next, choose Play->Stop from the Windows Media Player Main Menu or simply press Ctrl+S for Spy++ to log the WM_COMMAND message:

<00001> 0023017A P WM_COMMAND wNotifyCode:0 (sent from a menu) wID:18809

The Messages view appears as shown below. Note that the first column contains the window handle, and the second column contains a message code. Message parameters and return values are on the right.


Double click on this entry to view additional Message Properties such as the wParam and lParam hex values.


Repeating the above for the Start button yields:

<00001> 0023017A P WM_COMMAND wNotifyCode:0 (sent from a menu) wID:18808

Using P/Invoke and Spy++, it’s easy to extend functionality to include other options such as Eject, Repeat, or Volume control but for demonstration purposes, we shall only implement Start/Pause and Stop.

private System.Int32 iHandle;

private void btnStop_Click(object sender, System.EventArgs e)
    Win32.SendMessage(iHandle, Win32.WM_COMMAND, 0x00004979, 0x00000000);

private void btnPlayPause_Click(object sender, System.EventArgs e)
    Win32.SendMessage(iHandle, Win32.WM_COMMAND, 0x00004978, 0x00000000);

private void MainForm_Load(object sender, System.EventArgs e)
    // get Window handle
    iHandle = Win32.FindWindow("WMPlayerApp", "Windows Media Player"); 


I had fun writing this article even though it’s not an original idea, but hopefully somebody out there will find it useful enough. Originally, I was thinking to dig deep into Windows Media player using FindWindowEx() and start playing with ATL:SysListView32 the “Current Playlist” to manipulate Windows Media Player Playlists on selected remote machines using WMI. If anyone has any other ideas or feature request, just let me know.


  • Version 1.0 - February 08 2004 - Original submission.


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


About the Author

Alexander Kent
Kentdome LLC
United States United States
Biography in progress Wink | ;-)

You may also be interested in...

Comments and Discussions

QuestionBuffer Status Pin
Hardik Vaghani21-Mar-15 0:58
memberHardik Vaghani21-Mar-15 0:58 
QuestionPlaying file path ? Pin
jeffingeorge26-Feb-14 0:18
memberjeffingeorge26-Feb-14 0:18 
SuggestionWindows Media Pin
tri phan ba10-Feb-12 23:12
membertri phan ba10-Feb-12 23:12 
QuestionMany Questions Pin
eiladah16-Dec-11 5:14
membereiladah16-Dec-11 5:14 
QuestionHow I can get a player list? Pin
hendryck7-Nov-11 17:31
memberhendryck7-Nov-11 17:31 
QuestionHow set zoom to 200% Pin
TheCodeVB15-May-10 12:34
memberTheCodeVB15-May-10 12:34 
QuestionRef. sound card Pin
FlavioAR4-Apr-10 3:47
memberFlavioAR4-Apr-10 3:47 
GeneralDoesnt work with WMP 12 Pin
Fullmetal9901227-Feb-10 13:19
memberFullmetal9901227-Feb-10 13:19 
GeneralRe: Doesnt work with WMP 12 Pin
Fullmetal9901227-Feb-10 13:36
memberFullmetal9901227-Feb-10 13:36 
GeneralAlternate version using WM_APPCOMMAND and should work with most players Pin
Alain VIZZINI6-Dec-09 3:00
memberAlain VIZZINI6-Dec-09 3:00 
I used your code and it's very usefulThumbs Up | :thumbsup: ! It was my startup point. I just modified the fact that I use WM_APPCOMMAND (the same function as the recent keyboards with extra buttons) that is supported by most "players" (wmp, media player classic,...). Code is the same or so, juste message and parameters is different.

Code is here if it helps someone :[^]

Out of curiosity I didn't tested it on all players, so if it works with your own player, drop a reply please.

QuestionHow can i get Windows Media Player Status? Pin
Saccomani23-Aug-09 6:44
memberSaccomani23-Aug-09 6:44 
GeneralSmall mistake in code Pin
Idan Shimoni24-Jan-09 8:08
memberIdan Shimoni24-Jan-09 8:08 
GeneralRe: Small mistake in code Pin
icetea948-May-10 0:22
membericetea948-May-10 0:22 
GeneralDoes not work with Vista any more Pin
DeppChef21-Jul-08 10:00
memberDeppChef21-Jul-08 10:00 
GeneralRe: Does not work with Vista any more Pin
Idan Shimoni24-Jan-09 8:10
memberIdan Shimoni24-Jan-09 8:10 
QuestionVoice recording Pin
kaka sipahe27-Jun-08 3:53
memberkaka sipahe27-Jun-08 3:53 
GeneralNeed some help Pin
Scalee24-Jun-08 11:39
memberScalee24-Jun-08 11:39 
GeneralSpy++ Pin
zinneaj17-Jun-08 2:20
memberzinneaj17-Jun-08 2:20 
GeneralRe: Spy++ Pin
zinneaj17-Jun-08 2:35
memberzinneaj17-Jun-08 2:35 
QuestionwNotifyCode Pin
ncjlee8-Jun-08 21:01
memberncjlee8-Jun-08 21:01 
AnswerRe: wNotifyCode Pin
ncjlee8-Jun-08 23:03
memberncjlee8-Jun-08 23:03 
GeneralID3 Pin
turtle@inf.furb.br13-Feb-08 1:56
memberturtle@inf.furb.br13-Feb-08 1:56 
GeneralIt doesn`t work on wmp 11 Pin
nevecaju21-Jul-07 11:44
membernevecaju21-Jul-07 11:44 
GeneralRe: It doesn`t work on wmp 11 Pin
Virtual1ty15-Sep-07 8:58
memberVirtual1ty15-Sep-07 8:58 
GeneralRe: It doesn`t work on wmp 11 Pin
Virtual1ty15-Sep-07 9:07
memberVirtual1ty15-Sep-07 9:07 
GeneralVery useful Pin
breakall18-Apr-07 8:45
memberbreakall18-Apr-07 8:45 
QuestionCan this be used to change the visualizer? Pin
Judah Himango26-Dec-06 17:28
memberJudah Himango26-Dec-06 17:28 
Questionany way to determine wParam and lParam from menu item name? Pin
Dr. Chuck19-Oct-06 21:02
memberDr. Chuck19-Oct-06 21:02 
AnswerRe: any way to determine wParam and lParam from menu item name? Pin
Saccomani24-Aug-09 14:28
memberSaccomani24-Aug-09 14:28 
QuestionDetermining WMP Status? Pin
john@datavox.net10-Aug-06 12:56
memberjohn@datavox.net10-Aug-06 12:56 
GeneralSimply WOW! Pin
MANSATAN17-Jul-06 9:22
memberMANSATAN17-Jul-06 9:22 
GeneralSet MDIParent Property Pin
bboyle123425-Apr-06 20:19
memberbboyle123425-Apr-06 20:19 
GeneralRequest.. Pin
CSutherland7-Jan-06 16:02
memberCSutherland7-Jan-06 16:02 
GeneralGood article. Pin
CSutherland7-Jan-06 15:56
memberCSutherland7-Jan-06 15:56 
GeneralRe: Good article. Pin
iKevenaar12-Jul-09 3:49
memberiKevenaar12-Jul-09 3:49 
GeneralOther managed equivalent Pin
Adarsh Shah21-Dec-05 20:26
memberAdarsh Shah21-Dec-05 20:26 
GeneralThanks and very helpful Pin
AmanBhandari2-Dec-05 1:14
memberAmanBhandari2-Dec-05 1:14 
QuestionHow to control the save file dialog of WMP? Pin
caveman_19781-Nov-05 3:55
membercaveman_19781-Nov-05 3:55 
GeneralAny chance of a hand!! Pin
pokabot15-Jul-05 0:59
memberpokabot15-Jul-05 0:59 
GeneralRe: Any chance of a hand!! Pin
Alexander Kent15-Jul-05 10:06
memberAlexander Kent15-Jul-05 10:06 
GeneralRe: Any chance of a hand!! Pin
pokabot17-Jul-05 12:39
memberpokabot17-Jul-05 12:39 
GeneralRe: Any chance of a hand!! Pin
pokabot17-Jul-05 21:10
memberpokabot17-Jul-05 21:10 
Generaljuke box Pin
AAyub14-Jul-05 8:27
memberAAyub14-Jul-05 8:27 
GeneralRe: juke box Pin
Alexander Kent15-Jul-05 10:08
memberAlexander Kent15-Jul-05 10:08 
GeneralGreat Article Pin
tomcoleman17-Dec-04 9:04
membertomcoleman17-Dec-04 9:04 
Generalusing buttons instead of menu's Pin
Preet Sethi11-Oct-04 10:50
memberPreet Sethi11-Oct-04 10:50 
GeneralRe: using buttons instead of menu's Pin
flandersucf19-Jul-05 8:00
memberflandersucf19-Jul-05 8:00 
GeneralContext Menus... Pin
Jumpin' Jeff14-Sep-04 11:50
memberJumpin' Jeff14-Sep-04 11:50 
General30 Second Skip Ahead Pin
Bill West11-Feb-04 3:16
memberBill West11-Feb-04 3:16 
GeneralA better (documented) way - WM_APPCOMMAND Pin
eran_ru8-Feb-04 22:11
membereran_ru8-Feb-04 22:11 

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.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.160530.1 | Last Updated 8 Feb 2004
Article Copyright 2004 by Alexander Kent
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid