1

I have a simple service with the following code:

on Program.Main method I have the code which is generated by vs itself(2010):

static void Main()
    {
        ServiceBase[] ServicesToRun;
        ServicesToRun = new ServiceBase[] 
        { 
            new Service1() 
        };
        ServiceBase.Run(ServicesToRun);
    }

And in Service1.cs I have:

 protected override void OnStart(string[] args)
    {
        System.Media.SoundPlayer myPlayer = new System.Media.SoundPlayer(@"C:\doorbell-1.wav");
        myPlayer.Play();
    }

    protected override void OnStop()
    {
    }

I have omit writing the usual automatically generated c# codes to reduce the complexity.

Logically a sound should be played when I start the service but nothing happens when I start the service. Please note that:

1-I install the service using installUtill.exe. 2-The service runs under the localSystem account privilege. 3-Duration of the mentioned .wav file is 3Seconds.

How can I play that sound? Thanks in advance.

Ali.Rashidi
  • 1,284
  • 4
  • 22
  • 51
  • 1
    Possible duplicate of [Play wave file from a Windows Service (C#)](http://stackoverflow.com/questions/2143439/play-wave-file-from-a-windows-service-c) – Robear Apr 06 '16 at 01:00

3 Answers3

2

The simple answer is that you can't. Windows Services do not interact with the desktop, and thus they are not capable of using desktop functions like audio services.

Remember, Windows is a multi-user operating system. Can you imagine what would happen if 5 simultaneously logged in users started playing audio?

All users have what's known as a "Windows Station", and there is a special Windows Station for the user logged into the physical computer. Windows Services have a null or unique (non-interactive) Windows Station, and thus cannot interact with the console WS.

This Windows Station is what is used to redirect audio, and the audio in the console WS goes to the speakers. All other audio either is redirected to the network station they're using, or does nothing.

A more complex answer is that it might be possible, since the Windows Audio service is itself another service, and you might be able to interact with it directly, but this would be very low level and something you are probably not skilled enough to do.

Finally, it's possible to make services interact with the desktop. However, this is considered a deprecated function and is not always easy to use. It's also a huge security vulnerability, and makes your service susceptible to being used by malware to compromise a machine.

Erik Funkenbusch
  • 92,674
  • 28
  • 195
  • 291
  • Thanks for illuminating me. But I need to play it :( – Ali.Rashidi Mar 16 '14 at 21:04
  • How can I interact between a service and a windows application? – Ali.Rashidi Mar 16 '14 at 21:05
  • @AliRashidi - Microsoft's policy is that if you need to do that, then you should run a user application that interacts with your service through TCP/IP, Pipes, or shared memory and have your user application play the sound. This is how services like Antivirus, and others work. They have a client that runs when the user logs in to interact with the services. – Erik Funkenbusch Mar 16 '14 at 21:05
  • That seems complicated. Thanks a lot Erik :p – Ali.Rashidi Mar 16 '14 at 21:07
  • @AliRashidi - Yes, it is complicated. Because doing anything else is irresponsible. – Erik Funkenbusch Mar 16 '14 at 21:08
  • Such limitations often bother programmers. I think it is not impossible but rather non-standard – Ali.Rashidi Mar 16 '14 at 21:09
  • @AliRashidi - I didn't say it was impossible, I said that the simple answer was that you can't.. There's some information here, which suggests using the DirectX API's may work if you take over exclusive use of the audio device. http://stackoverflow.com/questions/2143439/play-wave-file-from-a-windows-service-c – Erik Funkenbusch Mar 16 '14 at 21:11
  • @AliRashidi - also, here is an example.. it's not simple, but it is possible. http://bresleveloper.blogspot.co.il/2012/06/c-service-play-sound-with-naudio.html – Erik Funkenbusch Mar 16 '14 at 21:16
  • I've tried that. it increases the complexity of my program. I don't want to use that. I think it doesn't worth. – Ali.Rashidi Mar 16 '14 at 21:18
  • @AliRashidi - Well, its the only way you're going to get audio to work in a service. Writing the directx code yourself would be even more complex. – Erik Funkenbusch Mar 16 '14 at 21:20
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/49851/discussion-between-ali-rashidi-and-erik-funkenbusch) – Ali.Rashidi Mar 16 '14 at 21:23
1

I've been searching all over the internet whole the last night. This question has been answered so many times but a simple answer is never given. If you have the same question there is a very simple but a tricky way to do something when the service asks for it.

Let's say you want to play a song when service starts.

first of all create an EventLog class:

public class EventLogEngine
{
    private string _sourceName, _logName;
    public EventLogEngine(string sourceName, string logName)
    {
        if (!EventLog.SourceExists(sourceName))
            EventLog.CreateEventSource(sourceName, logName);
        _sourceName = sourceName; _logName = logName;
    }
    public void WriteLog(string message, EventLogEntryType eventType, int Id)
    {
        EventLog.WriteEntry(_sourceName, message, eventType, Id);
    }
}

protected override void OnStart(string[] args)
{
 EventLogEngine eventWriter = new EventLogEngine("mySource","myLog");
eventWriter.WriteLog("sourceName","Service started",EventLogEntryType.Information,"anyId");
}

There is nothig about playing a sound till here and there is nothing complicated yet. But how to play a sound or do something else? Here is the answer :)

1-Go to control panel and open Event Viewer

2-Find your event log and click on it

enter image description here

3-On the right panel you will see your entries which you have write through your code.

4-Right click on the entry and select Attach Task To This Event!

enter image description here

So far you should have understood what I am going to do. right?

5-Select that option and declare what do you want to do when this entry is set. You can simply attach as many as tasks you wish.

enter image description here

Now write a program that plays a sound (Ex:in vb6) and tell Event Viewer to carry out this program each time this entry gets written(each time your service starts)

Ali.Rashidi
  • 1,284
  • 4
  • 22
  • 51
  • I would *HIGHLY* discourage anyone from using this technique. Apart from the fact that you're now making the OS do work your application should be doing, it's a configuration nightmare and will likely get reset when upgrading OS's and what not. On top of that, if you need to distribute this to other users it will be a huge pain. Finally, it's going to fill up your event log with useless events, which could well scroll off events you need too quickly. It's just poor design, and a huge hack. – Erik Funkenbusch Mar 19 '14 at 17:54
  • If this is the approach you want to take, I would instead create a scheduled task that runs your sound program, set the scheduled task to run as the logged in user, and then set the task to have no schedule but use the scheduled task API to trigger the job when you want. This way you're not filling up your event log. Still a huge hack, but better than this solution. – Erik Funkenbusch Mar 19 '14 at 17:57
  • You are totally right @ErikFunkenbusch but for now there is no any other way to implement what I want.It seems that it is impossible to play a sound from a service and it's the only way to do it. Besides we can clear log manually or automatically whenever we want – Ali.Rashidi Mar 19 '14 at 18:28
1

It is possible to play sounds from a windows service.

Play wave file from a Windows Service (C#)

Playing a sound from a service doesn't violate the rules of interactivity because it's not an interactive function: it's a notification.

Community
  • 1
  • 1
Robear
  • 986
  • 1
  • 11
  • 15