If you’ve ever used SQL Server, you know it comes with a little control program that allows you to start and stop the SQL Server service. Wouldn’t it be cool if you could write a small program to do the same with your service? Well you can, and today we’ll learn how.
Before we begin, I made a few little tweaks to the TimeLoggerService source code that will make it a bit easier to work with, and implement some of the things we’ll want to do in our control program.
public TimeLoggerService()
{
InitializeComponent();
// Set the timer to fire every twenty seconds
// (remember the timer is in millisecond resolution,
// so 1000 = 1 second. )
_timer = new Timer(20000);
// Now tell the timer when the timer fires
// (the Elapsed event) call the _timer_Elapsed
// method in our code
_timer.Elapsed += new
System.Timers.ElapsedEventHandler(_timer_Elapsed);
}
private void WriteToLog(string msg)
{
EventLog evt = new EventLog(“ArcaneTimeLogger”);
string message = msg + “: “
+ DateTime.Now.ToShortDateString() + ” “
+ DateTime.Now.ToLongTimeString();
evt.Source = “ArcaneTimeLoggerService”;
evt.WriteEntry(message, EventLogEntryType.Information);
}
protected override void OnStart(string[] args)
{
_timer.Start();
WriteToLog(“Arcane Start”);
}
protected override void OnStop()
{
_timer.Stop();
WriteToLog(“Arcane Stop “);
}
// This method is called when the timer fires
// it’s elapsed event. It will write the time
// to the event log.
protected void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
WriteToLog(“Arcane Timer”);
}
In the class constructor, the only change I made was to change the time from 60 seconds (60000 milliseconds) down to 20 seconds (20000 milliseconds). To be honest I got tired of waiting on it to log for my tests.
Next, I created a “WriteToLog” method that handles the actual writing of a message to the event log. This code is identical to what was previously in the timer_Elapsed event, except I take a passed in message and append the current date/time to the log. Note one other change, I modified it to use the LongTimeString instead of ShortTimeString, so I could get the seconds to display.
I then modified the OnStart and OnStop to log start and stop messages for me, which is probably a good idea for your service to do too. Finally I modified the _timer_Elasped event where I’d taken the WriteToLog code from, and made a call to our new method. OK, that takes care of changes to the windows service.
Now, let’s add a new project to our solution. In the Solution Explorer, right click on the solution name and pick Add Project, then pick Windows Application. Note that we could do this with a command line app or class library as well, but for this demo we’ll use a windows form. I gave my new app the imaginative name of “TimeLoggerManager”.
I renamed the Form1 to TLManager, and allowed VS to rename all the occurances of Form1 for me. I’m now going to add a few basic controls, one label (lblStatus), and two command buttons (btnStart and btnStop). I’m also going to add a timer control, tmrRefresh. Set the timer to enabled and pick a reasonable time, maybe every 10 or 15 seconds (10000 or 15000 in the Interval property, remember it gets set in milliseconds as well).
Now switch to code view on the form, and in the using area add a “using System.ServiceProcess” reference.
The first thing we need to do is find out what the status is of the service event. To do this we’ll first get a reference to our service by creating a ServiceController object, note in the “new” area we have to pass in the name of our service in order to get a reference to it. Once our object is created, I’ll pass it to a method that will set everything up for the form.
ServiceController sc = new ServiceController(“ArcaneTimeLogging”);
SetDisplay(sc);
Set Display is a custom method I wrote, here’s it’s code:
private void SetDisplay(ServiceController sc)
{
sc.Refresh();
if (sc.Status == ServiceControllerStatus.Stopped)
{
btnStop.Enabled = false;
btnStart.Enabled = true;
lblStatus.Text = “Stopped”;
}
if (sc.Status == ServiceControllerStatus.Running)
{
btnStart.Enabled = false;
btnStop.Enabled = true;
lblStatus.Text = “Running”;
}
}
The first thing called is sc.Refresh, this will cause the ServiceController to update all of the properties in our sc object with the correct values. Next I can query the Status property of our SC object, and set my command buttons and labels appropriately.
Starting and stopping our service is just as easy, all we have to do is create an instance of a service controller object, and then call it’s Start or Stop method.
private void btnStart_Click(object sender, EventArgs e)
{
ServiceController sc = new ServiceController(“ArcaneTimeLogging”);
sc.Start();
btnStart.Enabled = false;
btnStop.Enabled = true;
lblStatus.Text = “Running”;
sc.Refresh();
}
private void btnStop_Click(object sender, EventArgs e)
{
ServiceController sc = new ServiceController(“ArcaneTimeLogging”);
sc.Stop();
btnStop.Enabled = false;
btnStart.Enabled = true;
lblStatus.Text = “Stopped”;
sc.Refresh();
}
Because you can also start and stop the service from other locations, like VS or the MMC, it’s important to keep the display in sync. In the event for the timer, all we have to do is create another reference and pass it to the same SetDisplay method so everything stays in sync.
private void tmrRefresh_Tick(object sender, EventArgs e)
{
ServiceController sc = new ServiceController(“ArcaneTimeLogging”);
SetDisplay(sc);
}
Go ahead and give it all a try. Start your service, then check it in the MMC. Use MMC to stop the service, then watch the app automatically update to reflect the status.
Tomorrow we’ll look at sending commands to our windows service, then to wrap up the series we’ll look at integrating the event log into our application. Stay tuned!
i have created a windows service. now i need this service to run only on buisness days n buisness hours. Can u help me with the code.Taking in to consideration minimum resources being used,Thanks!
What about using Remoting over Ipc for communicating with the Windows Service?
i need to access the methods declared in the windows service from application? how to do that?
I was just searching a method to STOP and START SQL services and I got my answer at this post.
Thanks a lot…
🙂
Hi,
i need to save some data to the data base using windows services at regular tme intervals.need help…………….
my question is the same as kiran’s and shweta’s,
how I can run the windows service in specific business days and ours and also to make it inserts data to database.
btw; I already have these things done on normal windows applicationand I have a thread that wakes up on business hours and sleep otherwise. but how I canconvert this to windows service, or just tell me should this checking of business hours made on the windows service itself or in the application that launches it.
thanks
I, have a windows service project and a windows application project but i want to call windows application project from from windows service project , please explain with code and project example.
For those asking how to run the windows service only during business hours. Just use a timer object to execute a method on a periodic basis. When the method executes, just include logic to determine if the windows service should execute right now. If so, then call your method that you would normally would call when you execute your service.
Hey…..nice post!!
Awesome, No more words to explain 🙂 🙂 😀 just….cool blog.
how can i connect to a db from the windows server?
whats the best approach?
im very new to C#
how can i connect to a db from the windows server?
what about RPC calls from a windows service?
Utterly written content material , appreciate it for selective information .
hi very usefull 12 words, u changed my mind 🙂 im gonna save this one 🙂 thanksss x
I like the helpful info you provide in your articles. I will bookmark your weblog and check again here regularly. I’m quite certain I will learn many new stuff right here! Good luck for the next!
I have done this… but i got System.InvalidOperationException exception when i click on the start button
What to do this?
http://msdn.microsoft.com/query/dev10.query?appId=Dev10IDEF1&l=EN-US&k=k%28EHINVALIDOPERATION%29;k%28TargetFrameworkMoniker-%22.NETFRAMEWORK%2cVERSION%3dV4.0%22%29;k%28DevLang-CSHARP%29&rd=true
How could I use window service to connect to Window scheduler task and send some parameters to it?
I had a problem with security levels and couldn’t thus call Start()/Stop() methods without having an exception thrown.
This idea helped me; in case somebody else also had similar issues – voila!
http://www.designlimbo.com/?p=82