|
Build Your First .NET Windows Service (Continued)
Notice that you need to reference the ServiceProcess namespace in order to access Windows Service classes:
Imports System.ServiceProcess
You can create a reference to the ServiceProcess.dll component by going to Add Reference under the References folder of the Solution Explorer for the project (see Figure 3).
Once the ServiceProcess component is referenced, you can now access the ServiceController class, which is the key to working with Windows Services. You can query and control the service, and set almost all its properties through the ServiceController object. As you can see in the MonitorThis() method, the first thing you need to do is get an instance of the ServiceController object associated with the AppMonitor service. If it exists, the service's status is examined to make sure that it's running before you send a command to the service using the ExecuteCommand() method.
Now that you've written the MonitorWrapper class, it's time to deploy it for use by other desktop applications. Normally, you would deploy it to the GAC, but for purposes of simplicity in this article, let's create a project reference to it from a sample desktop application (SecurityController).
Create a Sample App to be Monitored
The SecurityController project is a simple .NET WinForms desktop application that we'll use as a proof of concept for the AppMonitor monitoring service. This mythical security control application references the MonitorWrapper class created earlier to send service commands associated with security events. In addition, the application also includes buttons to start and stop the AppMonitor service to show how to control a Windows Service through the ServiceController object (see Listing 3).
As you can see, commands are sent to the AppMonitor service through the MonitorThis() method (in the MonitorWrapper class). You can also add start and stop buttons and code to start and stop the AppMonitor service. As discussed earlier, you control the service through the ServiceController object. The only difference between sending a command to the service and changing a service's status is that you need to start and stop a service asynchronously.
You could start a service by calling the Start() method of the ServiceController object. However, this doesn't guarantee that the service will start. After calling Start(), you need to make a call to the WaitForStatus() method, which waits for a specified time span (or indefinitely, if no time span is specified) for the status to change to the desired state. If the WaitForStatus() method times out, an exception is thrown, which needs to be caught. This same logic also goes for stopping, pausing, or resuming a service.
Debugging a Windows Service is just like debugging any external process. Within the IDE, you can attach to a running Windows Service by using the Tools | Debug Process command. Bring up the code within the IDE, set your breakpoints, and debug as you would a normal application. Keep in mind that you're debugging a "live" process when debugging a Windows Service. If you hit a breakpoint, the service stops on the machine and doesn't respond to any other events. If you close the debugger/IDE without resuming the process, the service reverts to a stopped state and could result in instability within the service.
Now that you've deployed a simple monitoring service, you can see how you can extend this model easily. The fact is, you probably wouldn't use this kind of monitoring design in a production environment because it relies on file I/O and simplistic integer service commands. A more elegant (but complex) design would be to spin off a separate thread within the OnStart() method of the service. This thread would initialize a message queue for application monitoring commands. You could then revise the MonitorWrapper to communicate with the message queue instead of executing an integer command on the AppMonitor service itself. After the new Windows Service is ready to deploy, you could compile, reversion, and deploy a new MonitorWrapper class to the GAC to run side by side with the original version. You could give the new Windows Service a version-unique name so it could run side by side with the old AppMonitor service as well. You would merely need to recompile desktop applications with a reference to the new MonitorWrapper class in order to take advantage of the new monitoring design.
You now have the basics for developing Windows Services in .NET. As you can see, VS.NET 2003 makes it simple to create and deploy services, and the ability to hook into service events gives you a strong foundation for building even the most complex Windows Service in any .NET language. You can extend this simple architecture easily to make it more robust for your high-capacity production environment. This is a Getting Started column, so I'll shelve how to extend the AppMonitor service using threads and MSMQ for a future article. Stay tuned for this AppMonitor service upgrade, which will combine the use of some of the .NET technologies that I've written about in VSM over the past six months (including threads and MSMQ) with Windows Services, to provide an exciting monitoring architecture.
About the Author
Doug Thews is the director of software development for D&D Consulting Services in Dallas. Doug has more than 19 years of software-development experience in C/C++, VB/ASP, and VB.NET/C#. He writes the Getting Started column for Visual Studio Magazine, and coauthored the book, Professional ASP.NET Performance (Wrox/Wiley Press). Reach Doug at .
Back to top
|