I have a C# application that uses a Windows service that is not always on and I want to be able to send an email notification when the service starts and when it shuts down. I have the email script written, but I cannot seem to figure out how to detect the service status changes.
I have been reading up on the EDIT: Due to the fact that the ServiceController class and I think that the WaitForStatus() method might be what I need, but I haven’t been able to find an example with it being used on a service that is not yet started.WaitForStatus() method busy-waits and I need to be executing the rest of the program run by the service while listening for the service to start/stop, I don’t think that this is the method for me, unless someone has a solution that uses this method combined with multithreading and is clean and efficient.
More:
- the service will not be started by the application – the application user will be starting that directly from the Services window in the Administrative Tools.
- the service used is not a default Windows service – it is a custom service designed for use with this application
Thanks for your help!
P.S. please note that I’m fairly new to C# and am learning as I go here.
UPDATE:
I have managed to get the alert email to send each time the service starts: As I continued to read through the code that I have (which I, unfortunately, cannot post here), I noticed that the class used to create the service was extending the ServiceBase class and that someone made a custom OnStart() method to override the default one. I added the necessary method calls to the new OnStart() method and it successfully sent the notifications.
I attempted to do the same thing for the OnStop() method, but that did not work out so well for me – before I continue, I would like to add that I have been programming in Java for several years, and I am very familiar with Java design patterns.
What I attempted to do, which would have worked in Java, was override the ServiceBase class’s OnStop() method with one that calls the email notification, cast MyService to be of type ServiceBase and then re-call the ServiceBase class’s Stop() method (NOTE: OnStop() is a protected method so it could not be called directly – the Stop() method calls OnStop() and then continues with the necessary code to stop the service). I thought that casting to type ServiceBase would force the default OnStop() method to be called, instead of my custom one.
As you may imagine, I ended up with just under 10,000 emails successfully sent to my inbox before I managed to force my computer into a hard shutdown.
What I need now is a way to either use my overridden OnStop() method and then have it call the default method, or another solution to this problem. Any and all help is much appreciated. Thanks so much.
FOR THOSE OF YOU WITH MULTITHREADING SOLUTIONS:
protected override void OnStart(string[] args) {
string subject = "Notice: Service Started";
string body = "This message is to notify you that the service " +
"has been started. This message was generated automatically.";
EmailNotification em = new EmailNotification(subject, body);
em.SendNotification();
...INITIALIZE LISTENER FOR SERVICE STOPPING HERE...
...custom stuff to be run on start...
}
Also, remember that the class that this method is called in, let’s call it Service, extends the ServiceBase class.
UPDATE TWO:
In regards the suggestion that I use NotifyServerStatusChange I have learned that it is not permitted for the solution to use system functions, due to various reasons. To clarify, only solutions that are purely within the scope of C# and .NET are viable. Thanks, again, for your help!
Here is the solution and why I could not find it before: As I said earlier, my class extended the ServiceBase class. In my first update, I posted that I attempted to solve this in the same way I would have solved it with Java: through casting. However, in C# casting apparently doesn’t let you call the base method if you overrode it in the derived class. One of the things that I did not know when I first posted this question and this update (and clearly one of the things that no one thought of) was that C# includes the
baseconstructor that can be used to call methods of the base class from a derived class. As thebaseconstructor can be used for any class in C# it does not appear in the ServiceBase Class documentation.Once I learned this, I was able to take my original solution and modify it to use the base class:
I figured this out when I was playing around with the code in Visual Studio and noticed
basein my IntelliSense. I clicked to go to its definition and it sent me to ServiceBase (where it was obviously not defined). After noticing that base was not defined in my code and that it was an instance of the ServiceBase class I realized that it must have been some sort of constructor. After a quick Google search, I found what I was looking for. Way to go IntelliSense!Thank you everyone for all your help!