Calling Win32 DLLs in C# Using InteropServices

Calling Win32 DLLs via methods imported from a non-managed Win32 API using Platform Invocation Services (PInvoke) from C#.

By Tim Trott | C# ASP.Net MVC | November 28, 2011

How to import methods from a non-managed Win32 API call using Platform Invocation Services (PInvoke). PInvoke allows managed code to call unmanaged methods that are implemented in a DLL.

There are two ways that your C# code can directly call unmanaged code (code which .Net cannot see or have access to), a direct call to a function exported from a DLL or through a call to an interface method on a COM object. This tutorial deals with the former technique; the latter will be covered in a future tutorial.

To call an external unmanaged method, you must provide .Net with a declaration of the unmanaged method, and a description of how to marshal (use) the parameters and return value to and from the unmanaged code.

This shortcode sample will invoke a method called "PlaySound" from a DLL called "winmm.dll".

Firstly, you need to add a reference to System.Runtime.InteropServices

C#
using System.Runtime.InteropServices;

Next, we need to provide a declaration of the unmanaged code using the DllImport attribute. This tells .Net that the function is contained within a DLL called winmm.dll. This is a Windows built-in file and is found in the system path so you do not need to specify its full location.

C#
[DllImport("winmm.dll")]
public static extern bool PlaySound(string filename,long hmodule, int dword );

Notice that the methods are static (we do not have a class to instantiate) and we use the extern keyword which informs the compiler that the methods are external to the runtime.

All that is left to do now is to call the methods with parameters. The .Net Framework does not contain the flag's header information, so you must either declare them yourself or locate and use the bitwise values. In this example 0x0001 represents the old Win32 flag "SND_FILENAME" and 0x00020000 represents "SND_ASYNC". You can find these values on the Windows API  website.

The final code looks like this:

C#
using System;
using System.Runtime.InteropServices;
class PInvokeTest
{
  [DllImport("winmm.dll")]
  public static extern bool PlaySound(string pszSound, UIntPtr hmod, uint fdwSound);

  public static void Main()
  {
    bool result;
    result = PlaySound("C:\WINDOWS\Media\Chimes.wav", UIntPtr.Zero, 0x0001 | 0x00020000);
    Console.WriteLine(result);
  }
}

For a list of Win32 functions and parameters please refer to the Windows API Reference on the Microsoft site.

How to Beep the Internal PC Speaker in C# using Win32

This short snippet uses a system DLL call to legacy Win32 API which will sound the PC speaker at a given frequency and duration.

Internal PC Speaker
Internal PC Speaker
C#
[DllImport("Kernel32.dll")]
public static extern bool Beep(UInt32 frequency, UInt32 duration);
public static void BeepMe()
{
  int Frequency = 500;
  int DurationInMS = 100;
  Beep(Frequency, DurationInMS);
}

Cannot Beep PC Speaker in Windows 7 and Up?

As of Windows 7, 64-bit versions of Windows don't support the internal PC speaker beeps. At all. This code and Console.Beep will simply use the default sound device configured in Windows. See here for details - What's up with the Beep driver in Windows 7? 

Was this article helpful to you?
 

Related ArticlesThese articles may also be of interest to you

CommentsShare your thoughts in the comments below

If you enjoyed reading this article, or it helped you in some way, all I ask in return is you leave a comment below or share this page with your friends. Thank you.

This post has 4 comment(s). Why not join the discussion!

We respect your privacy, and will not make your email public. Learn how your comment data is processed.

  1. TM

    On Monday 20th of January 2014, tlhogi mmusi said

    what are the second and third parameters ( UIntPtr hmod and uint fdwSound);) , what do they mean and how does one know what values to pass them?

    1. Tim Trott

      On Wednesday 22nd of January 2014, Tim Trott  Post Author replied

      If the pszSound parameter is a resource identifier; hmod must identify the instance that contains the resource. Since we are playing a .wav file this is set to zero.

      fdwSound is a SoundFlags enum member, in this case 0x0001 is to play asynchronously and 0x00020000 means that the pszSound parameter is a file name.

      More info: https://pinvoke.net/default.aspx/winmm.playsound

  2. AN

    On Monday 23rd of November 2009, Anonymous said

    Error 1 The type or namespace name 'DllImport' could not be found (are you missing a using directive or an assembly reference?) C:\Documents and Settings\[Anonymous]\My Documents\Visual Studio 2008\Projects\[Private Project]\[Private Project]\Form1.cs 68 10 [Private Project]

    What to do?

    1. Tim Trott

      On Thursday 10th of December 2009, Tim Trott  Post Author replied

      Try adding

      using System.Runtime.InteropServices;