DevCity.NET - http://www.devcity.net
Controlling a Windows Service from the System Tray
http://www.devcity.net/Articles/74/1/servicecontroller.aspx
Peter Custance
I am currently a software programmer for a large Data Card Manufacturer in the UK. Contact me at peter.custance@id-data.co.uk or p.custance@btopenworld.com.
I have nine years experience in software programming, using C and Visual Basic on Windows and Linux. I have been using VB.NET since beta 2 and I have built 2 websites using ASP 3 and ASP.NET. Visit www.britxchange.com or my homepage at www.custec.co.uk. I am now using the Visual Studio.Net 1.0 release daily and believe it to be the best development IDE available.
by Peter Custance
Published on 2/26/2003
VB.NET contains built in classes which make creating a windows service a breeze, but what if you want an application to control a service which is easy for anyone to use. This article will show you how to create an application that runs in the system tray. We will not be discussing the creation of a service. Instead we will use this application to control IIS.
Controlling a Windows Service from the System Tray
Article source code: servicecontroller.zip
VB.NET contains built in classes which make creating a windows service a breeze, but what if you want an application to control a service which is easy for anyone to use. This article will show you how to create an application that runs in the system tray. We will not be discussing the creation of a service. Instead we will use this application to control IIS. This could be a great help for developers creating ASP and ASP.NET applications where it is useful to be able to re-start the web server without delving into Settings. The images below shows the application running.
To develop this type of application you will start with a WinForm Project and delete the form it creates. We will run this application from a Sub Main procedure in a module you should add to your project.
Imports System.Diagnostics
Imports System.Text
Public Module modMain
Private mobNotifyIcon As NotifyIcon
Private WithEvents mobContextMenu As ContextMenu
Private WithEvents mobTimer As Timers.Timer
Private mobServiceController As System.ServiceProcess.ServiceController
End Module
The code above imports the Diagnostics
and Text
namespaces that we will need later on in the code. A NotifyIcon
is declared which will show in the system tray and a ContextMenu
to display the user menu. We also need a timer to keep a check on the status of our service and update the menu and icon. A ServiceController
is then declared. Before you go further into the coding take some time out to create three icons to represent the stopped, running and paused status of the service. The ones I have created below resemble traffic lights, but you can use any analogy you wish. VS.NET allows you to create icons within the IDE...which is nice!
Next we need to add a procedure to set up the timer and start it running. Set the interval at five seconds which is usually about the time IIS takes to start or stop.
Private Sub SetUpTimer()
Try
mobTimer = New Timers.Timer()
With mobTimer
.AutoReset = True
.Interval = 5000
.Start()
End With
Catch obEx As Exception
Throw obEx
End Try
End Sub
To create the menu we will add a procedure that adds MenuItems
to the ContextMenu
and sets up the Event Handlers. Of course it may not be possible to Pause/Continue some services but what we are creating here is generic and will work with any service. Later in the code we will check if Pause or Continue are possible and enable the menu items accordingly.
Private Sub CreateMenu()
Try
mobContextMenu.MenuItems.Add(New MenuItem("Stop", _
New EventHandler(AddressOf StopService)))
mobContextMenu.MenuItems.Add(New MenuItem("Pause", _
New EventHandler(AddressOf PauseService)))
mobContextMenu.MenuItems.Add(New MenuItem("Continue", _
New EventHandler(AddressOf ContinueService)))
mobContextMenu.MenuItems.Add(New MenuItem("Start", _
New EventHandler(AddressOf StartService)))
mobContextMenu.MenuItems.Add("-")
mobContextMenu.MenuItems.Add(New MenuItem("About", _
New EventHandler(AddressOf AboutBox)))
mobContextMenu.MenuItems.Add(New MenuItem("Exit", _
New EventHandler(AddressOf ExitController)))
Catch obEx As Exception
Throw obEx
End Try
End Sub
As you change the status of the service you will want to reflect this to the user by changing the icon displayed. We must also establish the status of the service when the application starts. The GetServiceStatus
procedure below first of all, calls the Refresh
method of the ServiceController
. This will refresh all the properties of the controller and is essential in order to get accurate status information. A Select Case
statement then reads the status and sets up the menu and icon. Ensure that you have placed your icons in the bin directory of your project with the executable. If you wish to take this a step further you could create a resource file for the icons and enumerate the Menu indexes.
Private Sub GetServiceStatus()
Try
'//REFRESH PROPERTIES BEFORE READING.
mobServiceController.Refresh()
'//REFLECT STATUS IN THE CONTEXT MENU.
Select Case mobServiceController.Status()
Case ServiceProcess.ServiceControllerStatus.Paused
mobNotifyIcon.Icon = New Icon("Paused.ico")
mobContextMenu.MenuItems(0).Enabled = False
mobContextMenu.MenuItems(1).Enabled = False
mobContextMenu.MenuItems(2).Enabled = True
mobContextMenu.MenuItems(3).Enabled = False
Case ServiceProcess.ServiceControllerStatus.Running
mobNotifyIcon.Icon = New Icon("Running.ico")
mobContextMenu.MenuItems(0).Enabled = True
mobContextMenu.MenuItems(1).Enabled = True
mobContextMenu.MenuItems(2).Enabled = False
mobContextMenu.MenuItems(3).Enabled = False
Case ServiceProcess.ServiceControllerStatus.Stopped
mobNotifyIcon.Icon = New Icon("Stopped.ico")
mobContextMenu.MenuItems(0).Enabled = False
mobContextMenu.MenuItems(1).Enabled = False
mobContextMenu.MenuItems(2).Enabled = False
mobContextMenu.MenuItems(3).Enabled = True
Case _
ServiceProcess.ServiceControllerStatus.ContinuePending, _
ServiceProcess.ServiceControllerStatus.PausePending, _
ServiceProcess.ServiceControllerStatus.StartPending, _
ServiceProcess.ServiceControllerStatus.StopPending
mobNotifyIcon.Icon = New Icon("Paused.ico")
mobContextMenu.MenuItems(0).Enabled = False
mobContextMenu.MenuItems(1).Enabled = False
mobContextMenu.MenuItems(2).Enabled = False
mobContextMenu.MenuItems(3).Enabled = False
End Select
'//FINALLY CHECK IF PAUSE & CONTINUE IS POSSIBLE ON THIS SERVICE.
If mobServiceController.CanPauseAndContinue = False Then
mobContextMenu.MenuItems(1).Enabled = False
mobContextMenu.MenuItems(2).Enabled = False
End If
Catch obEx As Exception
Throw obEx
End Try
End Sub
With the menu under control we can now set up the event handlers we named in the procedure CreateMenu
. The code below shows an example and the others are very similar. You can find the code for the other events in the project download.
Private Sub StopService(ByVal sender As Object, ByVal e As EventArgs)
Try
If mobServiceController.Status = _
ServiceProcess.ServiceControllerStatus.Running Then
If mobServiceController.CanStop = True Then
mobServiceController.Stop()
End If
End If
Catch obEx As Exception
Throw obEx
End Try
End Sub
In order for your system tray icon to reflect the status of your service we need to call the GetServiceStatus
using our timer Elapsed
event.
Public Sub mobTimer_Elapsed(ByVal sender As Object, _
ByVal e As System.Timers.ElapsedEventArgs) Handles mobTimer.Elapsed
Try
GetServiceStatus()
Catch obEx As Exception
Throw obEx
End Try
End Sub
Finally when we exit the application we must do some tidying up of objects. Although the framework will periodically come round and collect your garbage, it is good programming practice to do a little housekeeping where you can.
Private Sub ExitController(ByVal sender As Object, ByVal e As EventArgs)
Try
mobTimer.Stop()
mobTimer.Dispose()
mobNotifyIcon.Visible = False
mobNotifyIcon.Dispose()
mobServiceController.Dispose()
Application.Exit()
Catch obEx As Exception
Throw obEx
End Try
End Sub
Well that about wraps up the code. Now you have seen how easy it is to control a service you may be itching to program your own. Maybe an app to keep an eye on your disc space and warn you when it is getting low or disc clean-up service. These are some of the ideas that may be the subject of a future article.
window.print();
_uacct = "UA-504168-3";urchinTracker();