Service Basics


A service has three basic characteristics:

  • A service might run all the time, even when the computer doesn't have anyone logged on or when the computer first starts.

  • A service doesn't have a user interface.

  • A service can be managed and controlled by both local and remote clients.

When deciding whether you need to write your application as a service or as a normal user-mode application, you need to ask yourself whether the development problem you're trying to solve has these three requirements. If it does, you should consider writing your application as a service. And if you do decide to write a service—and want to be able to debug it—you need to make sure you have a solid understanding of how a service operates. The information I'll present in this section will be just enough to give you an idea of what you're getting yourself into. If you'd like to learn more about services, I suggest you take a look at the excellent book by Jeffrey Richter and Jason Clark, Programming Server-Side Applications for Microsoft Windows 2000 (Microsoft Press, 2000).

A perfect example of when to write a service is when you're writing an application that needs to monitor an uninterruptible power supply (UPS). All the UPS software needs to do is to monitor when the UPS hardware reports a power failure, and when the power does go out, the UPS software needs to initiate a controlled shutdown. Obviously, if the UPS software isn't running all the time (the first criterion for deciding whether your application should be a service), the shutdown won't happen and the computer will just stop when the UPS hardware runs out of battery power. The UPS software doesn't really need a user interface (the second criterion) because it just needs to run in the background and monitor the UPS hardware. Finally, if you're working on UPS hardware for use in data centers, system administrators will definitely want to check on the health of remote UPS hardware (the third criterion).

Sounds simple enough—so far. Now we'll turn to the way services operate. The first aspect of services I'll cover is the specific API functions that you call to turn a normal user-mode process into a service.

The API Dance

Services have some unique qualities that will require some maneuvering on your part to accommodate. First, the entry point you use in services—main or WinMain—doesn't matter. Because your service doesn't have any user interface, you can use console or graphical user interface (GUI) entry points interchangeably.

Inside your main or WinMain processing, the first call you have to make is to the StartServiceCtrlDispatcher API function. You pass a SERVICE_TABLE_ENTRY structure to StartServiceCtrlDispatcher in which you indicate your service name and the main entry point of your service. The Service Control Manager (SCM), which starts all services and is what StartServiceCtrlDispatcher eventually talks to in order to set up your service, is an operating system feature that, as its name implies, controls all services. If your service doesn't call StartServiceCtrlDispatcher within 30 seconds of starting, the SCM will terminate your service. As you'll see later in the chapter, this time limit can make debugging startup a little more interesting.

As soon as you call into the SCM, the SCM spawns a thread to call your service's entry point. Your service's entry point has one hard requirement: it must register a handler with RegisterServiceCtrlHandlerEx and call SetServiceStatus within 82 seconds of starting. If your service doesn't make the calls within that time, the SCM thinks your service has failed, though it doesn't terminate the service. If your service eventually does call RegisterServiceCtrlHandlerEx, your service will run normally. Although you'd expect that the SCM would terminate your service if it thought your service had failed, it doesn't. Odd as this behavior is, it does make debugging as your service continues to run much easier.

RegisterServiceCtrlHandlerEx takes yet another pointer to a function, called the handler function. The SCM calls into the handler function to control your service's performance on operations such as stopping, pausing, or continuing.

When your service is transitioning from the states of starting, stopping, and pausing, it communicates with the SCM through the SetServiceStatus API function. Most services just need to call SetServiceStatus and indicate the basic state to which they're changing—there's nothing fancy about this API function.

I've glossed over a few of the details involved with the API functions, but basically the calls to StartServiceCtrlDispatcher, RegisterServiceCtrlHandlerEx, and SetServiceStatus are all that the operating system requires of your service to get it up and running. Notice that I didn't mention anything about requirements concerning communications protocols your service uses to communicate between a controller user interface you write and your service. Fortunately, services have access to all the regular Windows API functions, so you can use memory-mapped files, mail slots, named pipes, and so on. With services, you really have all the same options as you do in normal cross-process communications. The most challenging issue with services, as I pointed out at the beginning of the chapter, is security.

The Security Dance

Unless you specify otherwise, services run in a special account called the System account. Because Windows has user-based security for all objects, the System account is validated for the machine, not for the network as a whole. Consequently, a System account process can't access network resources. For many services, such as the UPS example mentioned earlier in this chapter, the security issues might never arise during development. But if you're trying to share mapped memory from your service to the UI client application, for example, and your security isn't set correctly, you'll run into access-denied errors from your client applications as they attempt to map the shared memory.

Unfortunately, no amount of debugging will solve security problems; you have to make sure that you program both your services and your client applications with the security aligned correctly. Complete Windows security programming is a book unto itself, so be prepared to spend some time planning your security programming from the beginning of development. For a quick introduction to the range of security issues with services, I strongly suggest that you read Frank Kim's article "Why Do Certain Win32 Technologies Misbehave in Windows NT Services?" in the March 1998 Microsoft Systems Journal. Other excellent resources are Keith Brown's "Security Briefs" column in Microsoft Systems Journal and his book Programming Windows Security (Addison-Wesley, 2000). Finally, one of the best books ever written about real-world Windows security is Writing Secure Code, Second Edition by Michael Howard and David LeBlanc (Microsoft Press, 2003).

Now that you've had a whirlwind tour of services, let's turn to the real heart of this chapter: how to debug services.




Debugging Applications for Microsoft. NET and Microsoft Windows
Debugging Applications for MicrosoftВ® .NET and Microsoft WindowsВ® (Pro-Developer)
ISBN: 0735615365
EAN: 2147483647
Year: 2003
Pages: 177
Authors: John Robbins

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net