A Windows Service is an application that does not have a user interface. It commonly runs without human intervention and can be automatically started when the computer starts up. Examples of Windows Services are the Internet Information Server (IIS), Telnet, and FTP. Windows Services WERE FORMERLY KNOWN AS NT Services. In this Article, I will illustrate how to create a windows service using Visual studio .net 2003.
Developing The TimeService Windows Service
In this article, I will develop a simple Windows Service that returns the current date and time. I will use the network example as illustrated in my earlier article. When this Windows Service is started, the server will start listening for all incoming network connections at Port 500. Regardless of What The Client Sends, The Windows Service Will Return The Current Date and Time.
Let's now build our Windows Service:
1. Launch Visual Studio .NET 2003 and create a new project.2. Select The project Types (Visual Basic Projects) and The Templates (Windows Service) .3. Name The Project TimeService (See Figure 1).
Figure 1. Creating a New Windows Service Project
4. Right-click on the design surface and select Properties. 5. Change the ServiceName property to TimeService. Also, set the CanPauseAndContinue property to True (see Figure 2). You want to be able to pause and resume the Windows Service after you Have STARTED IT.
Figure 2. Naming the Windows Service
6. Right-Click On The Design Surface and SELECT Add Installer (See Figure 3).
Figure 3. Adding the installer
7. Two installers will be added: ServiceProcessInstaller1 and ServiceInstaller1 (see Figure 4) These two controls are used by the InstallUtil.exe utility when installing the Windows Service (more on this in the next section) .Figure 4. Adding the two Installer. CONTROLS
8. Right-click on ServiceProcessInstaller1 and select Properties. Set the Account property to LocalSystem. 9. Right-click on ServiceInstaller1 and select Properties. Set the StartType to Manual. 10. Finally, double-click on the design surface to reveal the two DEFAULT METHODS, OnStart () and onstop () (See Figure 5).
Figure 5. The default onstart () and onstop () Methods
Now for the coding. First, Import The Following Namespaces:
Imports system.net.sockets
Imports system.net
Imports System.Text
Imports system.threading
You Have Also Need to Declare The Following Global Variables:
DIM T1 AS New Thread (Addressof Listen)
Dim canstoplistening as boolean = false
Dim Pause as boolean = false
DIM log as new system.diagnostics.eventlog
I have a subroutine named Listen () that repeatedly listens for incoming network requests. When a client is connected, it will send the current date and time. The global variables canStopListening and pause control the status of the loop.
Private sub listen ()
Const portno as integer = 500
Dim localadd as system.net.ipaddress = _
Ipaddress.parse ("127.0.0.1")
DIM Listener As New TCPListener (Localadd, Portno)
Listener.start ()
DO
IF not pause dam
DIM TCPCLIENT AS TCPCLIENT = listener.accePttcpClient ()
DIM NWSTREAM As NetworkStream = TcpClient.getStream
DIM BYTESTOREAD (TCPCLIENT.ReceiveBuffers) as byte
'--- Read incoming stream
DIM NumBytesRead as integer = _
NWStream.read (bytestoread, 0, _cint (tcpclient.receivebuffear))
'--- Write to Event Log
Log.WriteEntry ("received:" & _
Encoding.ascii.getstring (bytestoread, _
0, NumbytesRead & "@" & now)
'--- Write Time Back to Client
DIM Time () as byte = _
Encoding.ascii.getbytes (now.toString)
NWStream.write (Time, 0, Time.length)
TcpClient.close ()
END IF
Loop unsteil canstoplistening
Listener.stop ()
End Sub
The OnStart () event is invoked when the Windows Service is first started. And in this event, I have spun off the Listen () subroutine as a separate thread. I then log a message indicating that the service has started, using the event log . Using the event log is a good way to help debug your Windows Service Debugging Windows Services is not a trivial task -. Windows Services run in the background and within the context of Services Control Manager (and not within Visual Studio .NET) - - You Cannot Debug Windows Services With Visual Studio .NET. Thus, a Good Way To Debug Windows Services Is To Use The Event Log for Logging Events.
Protected Overrides Sub onstart (Byval Args () AS String
T1.Start ()
Me.autolog = false
IF not EventLog.sourceExists ("Time Service Log") THEN
EventLog.createEventSource ("Time Service Log", "MyLogfile")
END IF
Log.Source = "Time Service Log"
Log.WriteEntry ("Service Started")
End Sub
Note that you can not have a infinite loop within the OnStart () event, as control needs to be returned to operating system when the service is started. Hence I have spun off a thread (which runs continuously) to perform the actual reading of incoming data . The rest of the eventforward:
Protected Overrides Sub onstop () 'Invoked When the Service IS Stopped
Canstoplistening = true
Log.WriteEntry ("Service Stopped")
End Sub
Protected overrides subs onpause ()
'Invoked When the Service IS Paused
Pause = true
Log.WriteEntry ("Service Paused")
End Sub
Protected overrides subtontinue ()
'Invoked When a Service IS Continued
PAUSE = FALSE
Log.WriteEntry ("Service Continued")
End Sub
Once the coding is done, you can build the Windows Service by clicking on Build-> Build Solution. Installing the ServiceOnce the project is built, you need to install the Windows Service. The .NET framework provides the Installutil.exe utility. To install The Windows Service That You Have Just Built, Launch The Visual Studio .NET Command Prompt Window: 1. Navigate to the Directory Containing The Project Files and Type In The Following:
C: /.../ Windows Services / TimeService / bin> InstallUtil TimeService.exe
2. IF The Installation IS Successful, You Should See Something Like The Following Screen (Figure 6):
Figure 6. Installing the TimeService Windows ServiceNote that if you need to make changes to your Windows Service after it has been installed, you need to uninstall it first before you build the new version. You would also need to stop the service, if it has Been Started (more on this in the next section). To uninstall the installed windows service, use the / u Option, Like this:
Installutil / U TimeService.exe
Starting the serviceonce The service is successfully installed, you need to start the service. You can use the folload:
C: /.../ Windows Services / TimeService / bin> Net Start TimeService The TimeService
Service is starting.
The TimeService Service Was Started Success, You Can Also Start The Service Using The Services Utility Found Wtem, the Administrative Tools Grouping in Control Panel (See Figure 7).
Figure 7. Locating The TimeService In The Services UtilityTesting The ServiceTo Test The TimeService, You Will Use The Client Examples Ill Use Some Modifications Here:
Imports System.Text
Imports system.net
Imports system.net.sockets
Module Module1
Sub main ()
Const portno = 500
Const texttosend = "anything"
DIM TCPCLIENT AS New System.Net.Sockets.tcpClient
TcpClient.connect ("127.0.0.1", portno)
DIM NWSTREAM As NetworkStream = TcpClient.getStream
DIM BYTESTOnd As Byte () = Encoding.ASCII.GETBYTES (TextTosend)
'--- Send the Text
Console.writeline ("Sending:" & TextTosend)
NWSTream.write (bytestosnd, 0, bytestosnd.length)
'--- Read Back The Text
DIM BYTESTOREAD (TCPCLIENT.ReceiveBuffers) as byte
Dim numbytesread = nwstream.read (Bytestoread, 0, _
TcpClient.receiveBuffersize)
Console.writeline ("Received:" & _
Encoding.ascii.getstring (bytestoread, 0, _
NumbytesRead))
Console.readline ()
TcpClient.close ()
End Sub
End module
Basically, the client will send a message to the server hosting the TimeService Windows Service (which is the local host, anyway) and read the date and time returned by the service. If your Windows Service is installed and started correctly, you should see the Result Shown in Figure 8 WHEN You Run The Client Application.
Figure 8. Running the clientDuring the lifetime of the TimeService Windows Service, it will log all sorts of information into the event log (as evident in our code). You can view the event log by going to Control Panel-> Administrative Tools-> Event Viewer Look under the MyLogFile item and you should see a list of event messages (see Figure 9):. Figure 9. Viewing the event logControlling Windows Services using the ServiceController ClassOnce a Windows Service is installed, you can control its state using codes. In this section, I will illustrate controlling a Windows Service using the ServiceController class. The ServiceController class allows a Windows Service to be started, stopped, paused, or continued. 1. Create a Windows application and name it WinAppServiceController. 2. On the toolbox Click ON The Components Tab and Double-Click ON ServiceController (See Figure 10).
Figure 10. Adding the ServiceController control3. Change the MachineName and ServiceName properties of ServiceController1 to the machine name and the name of the Windows Service to control, respectively (see Figure 11).
Figure 11. Changing The Machinename and Servicename Properties4. Add The Following Buttons To Your Windows Form (See Figure 12):
Figure 12. Creating The Windows Application5. Key in The Codes Shown in Bold Below:
Private sub button1_click_1 (byval sender as system.object, _
ByVal e as system.eventargs)
Handles button1.click
ServiceController1.Start () 'for the start button
End Sub
Private sub button2_click_1 (byval sender as system.object, _
ByVal e as system.eventargs)
Handles Button2.click
ServiceController1.pause () 'for the pause button
End Sub
Private sub button3_click_1 (byval sender as system.object, _byval e as system.eventargs) _
Handles Button3.click
ServiceController1.stop () 'for the stop button
End Sub
Private sub button4_click_1 (byval sender as system.object, _
ByVal e as system.eventargs)
Handles Button4.click
'for the check status button
ServiceController1.refresh ()
Msgbox (ServiceController1.status.toString)
End Sub
Private sub Button9_click (Byval Sender as system.Object, _
ByVal e as system.eventargs)
Handles Button9.click
ServiceController1.Continue () 'for the Continue Button
End Sub
That's about it. Press F5 to test your application. Note that some Windows Services do not have an onPause () method. Therefore, before a service is paused, it is advisable for you to check whether it can be paused, or a runtime error Will Occur. You can do so use the canpauseandContinue property.
IF ServiceController1.canpauseandContinue Then
ServiceController1.pause () 'for the pause button
Else
"" Service cannot be paused. ")
END IF
Besides Using The ServiceController Control from The Toolbox, The ServiceController Can Also Be Invoked from Code, As The Following Code Shows:
DIM Controller As New System.ServiceProcess.ServiceController ("TimeService")
Retrieving the List of Windows Services Running on Your SystemBesides controlling a single Windows Service, you can also retrieve the list of Windows Services running on your system. In this section, I will extend the Windows application built in the previous section to get a list of all of the Windows Services installed on your system and to be able to start, stop, or pause the services. 1. Using the application built earlier, extend the Windows form to incorporate the following Button, Label, and ListBox controls (see Figure 13 ) .Figure 13. extending The Windows Application2. Type in The Following Code:
Private sub button6_click (byval sender as system.Object, _
ByVal e as system.eventargs)
Handles Button6.click
'--- for the start button ---
DIM Controller As New_
System.ServiceProcess.ServiceController (listbox1.selectedited)
Controller.Start ()
End Sub
Private sub button7_click (byval sender as system.object, _
ByVal e as system.eventargs)
Handles Button7.click
'--- for the pause button ---
DIM Controller As New_
System.ServiceProcess.ServiceController (listbox1.selectedited)
If Controller.canpauseandContinue Then
Controller.pause ()
Else
MsgBox ("Service Cannot Be Paused")
END IF
End Sub
Private sub button8_click (byval sender as system.Object, _
ByVal e as system.eventargs)
Handles Button8.click
'--- for the stop button ---
DIM Controller As New_
System.ServiceProcess.ServiceController (listbox1.selectedited)
Controller.stop ()
End Sub
Private sub button5_click_1 (byval sender as system.object, _
ByVal e as system.eventargs)
Handles Button5.click
'--- for the get service button ---
DIM controller as new system.serviceProcess.ServiceController ()
DIM Services () as system.serviceProcess.ServiceControllerdim i as integer
Services = controller.getServices ()
For i = 0 to Services.Length - 1
Me.Listbox1.Items.add (Services (i) .displayName)
NEXT
End Sub
Private sub placebox1_selectedindexchanged_1 (Byval Sender AS _
System.Object, ByVal e as system.eventargs_
Handles listbox1.selectedIndexchanged
'--- when the listbox is copy ---
DIM Controller As New_
System.ServiceProcess.ServiceController (listbox1.selectedited)
Label1.text = listbox1.selectedItem & "-" & _
Controller.status.tostring
End Sub
To test the application, Press F5. You Should See Something Like Figure 14. Click on the start, pause, and stop button.
Figure 14. Getting the list of Windows Services running on the current systemSummaryWriting Windows Services is now much easier using Visual Studio .NET. However, debugging Windows Services is still a pretty challenging task. For that, I suggest that you test out your code in A Windows Application and Ascertain That IT Works Before Porting. Have Fun!