- Defining the Windows Service Project
- Adding Some Simple Test Code
- Registering the Service
- Creating the Test Program
- Bottom Line
Creating the Test Program
You now have a Windows service installed. It's easy to verify the presence of the service by using the Services console, found in the Administrative Tools folder of the Control Panel. In fact, open the Services console now to check for the service. Verify that the service is running, or the test application will fail. If the service isn't running, right-click it and choose Start from the context menu.
The test application is a generic Windows form application. You'll need to add buttons for starting and stopping the service, register a service access, and display the number of service accesses as a minimum. After you add the buttons, open Server Explorer. Locate the service you just created and drag it to the form. The IDE will add a new ServiceController component that you can use to access the service. The example names this component svcTrackAccess. Listing 3 shows the code required to test the Windows service.
Listing 3 Testing the New Windows Service
private: System::Void Form1_Activated(System::Object * sender, System::EventArgs * e) { // Validate the current service status. Enable or disable // buttons as necessary. if (svcTrackAccess->Status == ServiceControllerStatus::Running) btnStart->Enabled = false; else { btnStop->Enabled = false; btnAccess->Enabled = false; btnGetAccess->Enabled = false; } } private: System::Void btnStart_Click(System::Object * sender, System::EventArgs * e) { // Start the service. svcTrackAccess->Start(); // Wait for the service to start. svcTrackAccess->WaitForStatus( ServiceControllerStatus::Running, System::TimeSpan::FromMilliseconds(2000)); // Change the button configuration to match // the service status. if (svcTrackAccess->Status == ServiceControllerStatus::Running) { btnStart->Enabled = false; btnStop->Enabled = true; btnAccess->Enabled = true; btnGetAccess->Enabled = true; } } private: System::Void btnStop_Click(System::Object * sender, System::EventArgs * e) { // Verify that we can stop the service. if (svcTrackAccess->CanStop) // Start the service. svcTrackAccess->Stop(); else { // We can't stop the service. MessageBox::Show("Service Doesn't Support Stopping"); return; } // Wait for the service to start. svcTrackAccess->WaitForStatus( ServiceControllerStatus::Stopped, System::TimeSpan::FromMilliseconds(2000)); // Change the button configuration to match // the service status. if (svcTrackAccess->Status == ServiceControllerStatus::Stopped) { btnStart->Enabled = true; btnStop->Enabled = false; btnAccess->Enabled = false; btnGetAccess->Enabled = false; } } private: System::Void btnAccess_Click(System::Object * sender, System::EventArgs * e) { // Access the service. svcTrackAccess->ExecuteCommand(128); } private: System::Void btnGetAccess_Click(System::Object * sender, System::EventArgs * e) { EventLog *MyEvents; // Event log with service entries. // Generate an event log entry with the number of accesses. svcTrackAccess->ExecuteCommand(129); // Open the event log. MyEvents = new EventLog("Application"); // Look for the correct message. for (int Count = 0; Count < MyEvents->Entries->Count; Count++) { // Get the event registered by the service. if (MyEvents->Entries->get_Item(Count)->CategoryNumber == 99) if (MyEvents->Entries->get_Item(Count)->EventID == 1200) // Display the message MessageBox::Show(MyEvents->Entries->get_Item(Count)->Message); } }
What appears to be a lot of code really isn't. The code begins with the Form1_Activated() method that checks the current status of the service. When the service is running, the code disables the Start button. Likewise, a stopped service disables the Stop, Access, and Get Access buttons. I included this code so you could see how to configure a support application during startup.
When a user clicks Start, the btnStart_Click() method begins by starting the service. However, it's not a good idea to simply move on to the next step because a service can require several seconds to start. Consequently, the code uses the WaitForStatus() method to wait for the service to startat least it waits for two seconds. If the service takes longer than two seconds to start, in this case, there's probably something wrong and you shouldn't wait any longer. Your own Windows services will require timing because not all services are the same. When the service starts as expected, the code again enables and disables buttons as needed.
Clicking Stop calls the btnStop_Click() method. Notice that, in this case, the code checks to ensure that it can even stop the service. Some services are marked so that Windows can't stop them. When this situation occurs, the code displays a message box telling the user that it can't stop the service, and then exits. Otherwise, the code calls the Stop() method and waits as with the Start() method for the service to signal that it has stopped. Again, the code changes the buttons to match the situation.
The user clicks Access to increase the access count. All the code has to do, in this case, is call ExecuteCommand() with the correct command number, 128.
Remember that the Windows service can't interact directly with your application, but it can communicate with the event log. Consequently, when the user clicks Get Access, the code begins by calling ExecuteCommand() with the 129 command code. This act generates an event log entry. Now the code opens the application event log and begins looking through the entries for the one made by the Windows service. When it finds this entry, the code displays a message that contains the number of user accesses.