Play wave file from a Windows Service (C#)

10,141

Solution 1

Playing a wav file from a service is definitely possible, at least on Windows 7 (and most likely Vista), by using the Windows Core Audio APIs. I recently verified this by making a small test service using NAudio. I just downloaded the NAudio sources and copied the "Wsapi" parts from their NAudioDemo project. This was on Windows 7 Enterprise 64bit, but I don't think that matters. The service was using the LocalSystem account.
For the record, playing sounds from a service is a perfectly legitimate thing to do in an embedded setting.

Solution 2

You can do this via the PlaySound API via winmm.dll, in Windows Vista or above. Microsoft added a seperate session for 'System Sounds' that can be used even from services, by merely adding a flag.

I've formatted this properly to avoid issues with the c# 2017 IDE throwing a wobbly over the DllImport not being in a class named 'NativeMethods'.

using System.Runtime.InteropServices;
namespace Audio
{
    internal static class NativeMethods
    {
        [DllImport("winmm.dll", EntryPoint = "PlaySound", SetLastError = true, CharSet = CharSet.Unicode, ThrowOnUnmappableChar = true)]
        public static extern bool PlaySound(
            string szSound,
            System.IntPtr hMod,
            PlaySoundFlags flags);

        [System.Flags]
        public enum PlaySoundFlags : int
        {
            SND_SYNC = 0x0000,/* play synchronously (default) */
            SND_ASYNC = 0x0001, /* play asynchronously */
            SND_NODEFAULT = 0x0002, /* silence (!default) if sound not found */
            SND_MEMORY = 0x0004, /* pszSound points to a memory file */
            SND_LOOP = 0x0008, /* loop the sound until next sndPlaySound */
            SND_NOSTOP = 0x0010, /* don't stop any currently playing sound */
            SND_NOWAIT = 0x00002000, /* don't wait if the driver is busy */
            SND_ALIAS = 0x00010000,/* name is a registry alias */
            SND_ALIAS_ID = 0x00110000, /* alias is a pre d ID */
            SND_FILENAME = 0x00020000, /* name is file name */
            SND_RESOURCE = 0x00040004, /* name is resource name or atom */
            SND_PURGE = 0x0040,  /* purge non-static events for task */
            SND_APPLICATION = 0x0080, /* look for application specific association */
            SND_SENTRY = 0x00080000, /* Generate a SoundSentry event with this sound */
            SND_RING = 0x00100000, /* Treat this as a "ring" from a communications app - don't duck me */
            SND_SYSTEM = 0x00200000 /* Treat this as a system sound */
        }
    }
    public static class Play
    {
        public static void PlaySound(string path, string file = "")
        {            
            NativeMethods.PlaySound(path + file, new System.IntPtr(), NativeMethods.PlaySoundFlags.SND_ASYNC | NativeMethods.PlaySoundFlags.SND_SYSTEM);
        }
    }
}

Solution 3

Applied the NAudio to simply allow to play audio file.
http://bresleveloper.blogspot.co.il/2012/06/c-service-play-sound-with-naudio.html

Share:
10,141
ASalvo
Author by

ASalvo

Updated on June 04, 2022

Comments

  • ASalvo
    ASalvo almost 2 years

    I need to play a wav file from a C# application running as a Windows Service. I have tried both System.Media.SoundPlayer and a P/Invoke call to WinMM.dll (which is probably what SoundPlayer is doing).

    [DllImport("WinMM.dll")]
    private static extern bool PlaySound(string fname, int Mod, int flag); 
    

    If I run my code as a console application, the sounds play. When I run it from a service, no luck, and I guess I'm not surprised.

    So is there a way to play a sound from a windows service? Would something like DirectSound help? Or am I going to be stuck writing a console application and having the windows service app communicate with it as an intermediary?

    Thanks in advance

  • ASalvo
    ASalvo about 14 years
    From the link provided, an accpeted method of interacting with the user is to spawn a GUI application. I will explore this option more fully.
  • ASalvo
    ASalvo about 14 years
    Thanks! I just tried this out on 32-bit Vista and it worked fine. I also tried the Wave Playback (did not work) and Directsound playback (worked) included in the library. There are 2 limitations that I have seen, both of which I can live with for my project. First, with Wasapi, I could only get it to work (even with the demo app) in exclusive mode, which means no other apps could play a sound. For DirectSound, I couldn't get it to play a sound as my service stopped. But I can live with this.
  • elif
    elif about 13 years
    Is it possible that you provide some code? I tried to do what you said but I couldn't get the sound to play (even without the service).
  • Brad
    Brad almost 12 years
    There are plenty of reasons why you may want to have a service interacting with audio. Think of a headless audio encoding server, for example.
  • Mark Ribau
    Mark Ribau over 11 years
    I want to vote down because "wrong application type" is rather subjective. Use case: a build machine that runs otherwise headless, but gives an audible alert (and email alert) when a build fails, and must run without a user logged in. I want to upvote because you supply a link on how to deal with the desire to do this. I give you an upvote.
  • idanzalz
    idanzalz over 11 years
    "wrong application type" is unhelpful, without more information about what he is trying to do or at least giving a generic better solution. There are many legitimate reasons to use a service, even if you want it to beep every once in a while