Five steps to write a Windows service program in C language

Source: Internet
Author: User

Windows services are designed for applications that need to run in the background and for tasks that do not have user interaction. To learn the basics of this console application, C (not C + +) is the best choice. This article builds and implements a simple service program that queries the amount of physical memory available in the system, and then writes the results to a text file. Finally, you can write your own Windows services with the knowledge you have learned.

When he wrote the first NT service, he went to MSDN for an example. There he found an article Nigel Thompson wrote: "Creating a simple Win32 Service in C + +", this article comes with a C + + example. Although this article is a good explanation of the service development process, however, he still feels the lack of important information he needs. He wants to understand what framework to call, what functions to invoke, and when to invoke, but C + + does not make him much easier in this regard. The object-oriented approach is convenient, but because of the encapsulation of the underlying WIN32 function calls, it is not conducive to learning the basic knowledge of the service program. That's why he feels that C is better suited to writing a service for a primary service program or for simple background tasks. After you have a thorough understanding of the service program, you can write in C + + to get the most out of it. When he left his old job and had to transfer his knowledge to another person, it was easy to explain the NT service by using the example he wrote in C.

A service is a console program that runs in the background and implements tasks that do not require user interaction. The Windows NT/2000/XP operating system provides specialized support for service programs. People can use the Service Control Panel to configure the installed service program, which is the Windows 2000/xp Control Panel, "services" in the Administration tool (or in the start | Run dialog box, enter the services.msc/s--translator note). The service can be configured to start automatically when the operating system starts, so you do not have to start the service manually after restarting the system each time.

This article will first explain how to create a service that periodically queries the available physical memory and writes the results to a text file. Then guide you through the process of building, installing, and implementing the service.

First step: main function and global definition
  
First, include the header file that you want. Example to invoke the Win32 function (windows.h) and Disk File write (stdio.h):

#include <windows.h>
#include <stdio.h>
  
Next, define two constants:

#define SLEEP_TIME 5000
#define LOGFILE "C:\\myservices\\memstatus.txt"
  
SLEEP_TIME Specifies the millisecond interval between available memory for two consecutive queries. This constant is used when writing the service work cycle in the second step.

LOGFILE define the path to the log file, you will use the WriteToLog function to output the results of the memory query to the file, the WriteToLog function is defined as follows:

int WriteToLog (char* str)
{
file* log;
Log = fopen (LOGFILE, "A +");
if (log = = NULL)
return-1;
fprintf (log, "%s\n", str);
fclose (log);
return 0;
}
  
Declare several global variables to share their values between multiple functions of the program. In addition, do a forward definition of a function:

Service_status ServiceStatus;
Service_status_handle Hstatus;

void ServiceMain (int argc, char** argv);
void Controlhandler (DWORD request);
int Initservice ();
  
Now that the preparation is ready, you can start coding. A subset of the service console program. So, at the beginning you can define a main function, which is the entry point of the program. For the service program, the code for main is surprisingly short, because it only creates the dispatch table and initiates the control dispatcher.
  
void Main ()
{
Service_table_entry servicetable[2];
Servicetable[0].lpservicename = "Memorystatus";
Servicetable[0].lpserviceproc = (lpservice_main_function) ServiceMain;

Servicetable[1].lpservicename = NULL;
Servicetable[1].lpserviceproc = NULL;

To start the service's control dispatcher thread
StartServiceCtrlDispatcher (servicetable);
}
  
A program may contain several services. Each service must be listed in a dedicated dispatch table (an array of servicetable structures is defined for this program). Each item in this table is in the service_table_entry structure. It has two domains:

Lpservicename: A pointer to a string representing the service name, and when multiple services are defined, the domain must be specified;
Lpserviceproc: Pointer to the service main function (service entry point);

The last item of the dispatch table must be a NULL pointer to the service name and the service main function domain, and the text example program only hosts one service, so the definition of the service name is optional.

The Service Control Manager (Scm:services Control Manager) is a process that manages all services of the system. When the SCM starts a service, it waits for the main thread of a process to call the StartServiceCtrlDispatcher function. Pass the dispatch table to StartServiceCtrlDispatcher. This converts the main thread of the calling process to the control dispatcher. The dispatcher starts a new thread that runs the ServiceMain function for each service in the dispatch table (only one service in this example) the dispatcher also monitors the execution of all services in the program. The dispatcher then passes the control request from the SCM to the service.

Note: If the StartServiceCtrlDispatcher function is not called for 30 seconds, it will be an error, in order to avoid this, they must initialize the service Dispatch table in the ServiceMain function (see the example in this article) or in a separate thread of the non-main function. The services described in this article do not need to be protected against such situations.

After all services in the dispatch table have finished executing (for example, the user stops them through the Services Control Panel program), or when an error occurs. The StartServiceCtrlDispatcher call returns. Then the main process terminates.

Step Two: ServiceMain function

void ServiceMain (int argc, char** argv)
{
BOOL BRet;

BRet = TRUE;
Servicestatus.dwservicetype =service_win32;
Servicestatus.dwcurrentstate =service_start_pending;
servicestatus.dwcontrolsaccepted =service_accept_stop | Service_accept_shutdown;
Servicestatus.dwwin32exitcode = 0;
Servicestatus.dwservicespecificexitcode = 0;
Servicestatus.dwcheckpoint = 0;
Servicestatus.dwwaithint = 0;
Hstatus = RegisterServiceCtrlHandler ("SERVICENAME", (lphandler_function) controlhandler);
if (Hstatus = = (service_status_handle) 0)
{
Login failed
Return
}

Service Status Intelligence Update
Servicestatus.dwcurrentstate = service_running;
SetServiceStatus (Hstatus, &servicestatus);

while (servicestatus.dwcurrentstate = = service_running)
{
int result = Startfunc ();
if (result)
{
Servicestatus.dwcurrentstate = service_stopped;
Servicestatus.dwwin32exitcode =-1;
SetServiceStatus (Hstatus, &servicestatus);
Return
}
}


Return
}

Step three: Build Your own Startfunc () function----write something if you want to write something. :)

Fourth Step: Install and configure the service
  
The program has been compiled to compile it into an EXE file. This example creates a file called MemoryStatus.exe and copies it to the C:\MyServices folder. In order to install this service on the machine, SC is required. EXE executable file, which is a tool included in the Win32 Platform SDK. (Translator Note: This tool is also available in the Visaul Studio. NET 2003 IDE Environment, located in: C:\Program Files\Microsoft Visual Studio. NET 2003\common7\tools\bin\ Winnt). Use this utility to install and remove services. Other control operations will be done through the Service Control Panel. Here's how to install the Memorystatus service using the command line:

SC Create memorystatus binpath= c:\MyServices\MemoryStatus.exe

Issue this create command. Specify the service name and the path to the binary file (note the space between binpath= and the path). Once the installation is successful, you can use the Service Control Panel to control the service (see figure I). Use the Control Panel's toolbar to start and stop the service.
The startup type of the Memorystatus is manual, which means that the service is started as needed. Right-click the service and select the Properties menu item in the context menu, which displays the Properties window for the service. Here you can modify the startup type and other settings. You can also start/stop the service from the "General" tab. Here's how to remove a service from your system:

SC Delete Memorystatus

Specify the "delete" option and the service name. The service will be marked for deletion and the service will be completely removed the next time the West Pass restarts

Note: The service is running on the XP system under C:\Windows\System32\.

2000 the system is running under c\winnt\system\.

So the program in the path of the place must be aware of.

In addition to these two systems, the other system has not been tested, but you can test it yourself, the generated directory in C:\memstatus.txt, the code is as follows:


#include <windows.h>
#include <stdio.h>

#define SLEEP_TIME 3000
#define LOGFILE "C:\\memstatus.txt"


int WriteToLog (char*);


Service_status ServiceStatus;
Service_status_handle Hstatus;

void ServiceMain (int argc, char** argv);
void Controlhandler (DWORD request);
int Initservice ();

int main ()
{
Service_table_entry servicetable[2];
Servicetable[0].lpservicename = "Memorystatus";
Servicetable[0].lpserviceproc = (lpservice_main_function) ServiceMain;

Servicetable[1].lpservicename = NULL;
Servicetable[1].lpserviceproc = NULL;

//
StartServiceCtrlDispatcher (servicetable);
return 0;
}


void ServiceMain (int argc, char** argv)
{
int error;

Servicestatus.dwservicetype = Service_win32;
Servicestatus.dwcurrentstate = service_start_pending;
servicestatus.dwcontrolsaccepted = Service_accept_stop | Service_accept_shutdown;
Servicestatus.dwwin32exitcode = 0;
Servicestatus.dwservicespecificexitcode = 0;
Servicestatus.dwcheckpoint = 0;
Servicestatus.dwwaithint = 0;

Hstatus = RegisterServiceCtrlHandler (
"Memorystatus",
(lphandler_function) Controlhandler);
if (Hstatus = = (service_status_handle) 0)
{
Return
}

Servicestatus.dwcurrentstate = service_running;
SetServiceStatus (Hstatus, &servicestatus);

Char memory[256];

while (servicestatus.dwcurrentstate = = service_running)
{

GetCurrentDirectory (256,memory);

int result = WriteToLog (memory);
if (result)
{
Servicestatus.dwcurrentstate = service_stopped;
Servicestatus.dwwin32exitcode =-1;
SetServiceStatus (Hstatus, &servicestatus);
Return
}
Sleep (Sleep_time);
}
Return
}


void Controlhandler (DWORD request)
{
Switch (Request)
{
Case SERVICE_CONTROL_STOP:
WriteToLog ("Monitoring stopped.");

Servicestatus.dwwin32exitcode = 0;
Servicestatus.dwcurrentstate = service_stopped;
SetServiceStatus (Hstatus, &servicestatus);
Return

Case Service_control_shutdown:
WriteToLog ("Monitoring stopped.");

Servicestatus.dwwin32exitcode = 0;
Servicestatus.dwcurrentstate = service_stopped;
SetServiceStatus (Hstatus, &servicestatus);
Return

Default
Break
}

SetServiceStatus (Hstatus, &servicestatus);

Return
}

int WriteToLog (char* str)
{
file* log;
Log = fopen (LOGFILE, "A +");
if (log = = NULL)
return-1;
fprintf (log, "%s\n", str);
fclose (log);
return 0;
}

Let's see his code,////////////////.

Main.cpp

#include <windows.h>
void WINAPI ServiceMain (DWORD, char**);
void Controlhandler (DWORD);
int Intelligentstart ();
void Txtinput ();
void read ();
Service_status ServiceStatus;
Service_status_handle Hstatus;
int WINAPI WinMain (hinstance hinstance, hinstance hpreinst, LPSTR pchcmdline, int icmdshow)
{
Service_table_entry servicetable[2];
Servicetable[0].lpservicename = "Intelligentstart";
Servicetable[0].lpserviceproc = (lpservice_main_function) ServiceMain;

Servicetable[1].lpservicename = NULL;
Servicetable[1].lpserviceproc = NULL;

StartServiceCtrlDispatcher (servicetable);
return 0;

}


void WINAPI ServiceMain (DWORD ac, char **av)
{

Servicestatus.dwservicetype = Service_win32;
Servicestatus.dwcurrentstate = service_start_pending;
servicestatus.dwcontrolsaccepted = Service_accept_stop | Service_accept_shutdown;
Servicestatus.dwwin32exitcode = 0;
Servicestatus.dwservicespecificexitcode = 0;
Servicestatus.dwcheckpoint = 0;
Servicestatus.dwwaithint = 0;

Hstatus = RegisterServiceCtrlHandler ("Intelligentstart", (lphandler_function) controlhandler);
if (Hstatus = = (service_status_handle) 0)
{
Registering Control Handler failed
Return
}

The running status to SCM.
Servicestatus.dwcurrentstate = service_running;
SetServiceStatus (Hstatus, &servicestatus);

The worker loop of a service
while (servicestatus.dwcurrentstate = = service_running)
{
int result = Intelligentstart ();
if (result)
{
Servicestatus.dwcurrentstate = service_stopped;
Servicestatus.dwwin32exitcode =-1;
SetServiceStatus (Hstatus, &servicestatus);
Return
}
}
Return
}


void Controlhandler (DWORD request)  

   switch (request)  
   {  
      case service_control_stop: 
          servicestatus.dwwin32exitcode = 0; 
         Servicestatus.dwcurrentstate = service_stopped; 
         SetServiceStatus (Hstatus, &servicestatus);
         return;

Case Service_control_shutdown:
Servicestatus.dwwin32exitcode = 0;
Servicestatus.dwcurrentstate = service_stopped;
SetServiceStatus (Hstatus, &servicestatus);
Return

Default
Break
}

Report Current status
SetServiceStatus (Hstatus, &servicestatus);

Return
}


int Intelligentstart ()
{

Txtinput ();
return 0;
}

Write.cpp

#include <stdio.h>
#include <conio.h>
void Txtinput ()
{
FILE *FP;
Char st[20] = "Test new.\n";
Fp=fopen ("C:\\string.txt", "at+");

Fputs (ST,FP);

Fclose (FP);

return;
}

http://blog.csdn.net/w616589292/article/details/24265739

Five steps to write a Windows service program in C language

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.