Windows Service Management operations

Source: Internet
Author: User

A service program is an important class of programs on windows that do not interact with the user interface, but they are important to the system. Windows provides a special program for the Management Service program: The Service Control Manager, which basically deals with this program on the system's API for service control management. These API functions are described below through the operation of the service program

Get information on system services

In Windows systems there is a database dedicated to storing service information, and getting system service information is primarily done by looking in such a database. The main functions used are:

OpenSCManager: Open Database
SC_HANDLE WINAPI OpenSCManager(  __in          LPCTSTR lpMachineName,  __in          LPCTSTR lpDatabaseName,  __in          DWORD dwDesiredAccess);

This function is used primarily to connect the Service Control Manager on a specific computer and to open the database for the Service Control Manager.
The parameters of the function are:
Lpmachinename: Host Name
Lpdatabasename: Name of the service database in the host
dwDesiredAccess: What permissions to open the service program
The first two parameters can be null, if it is null, the second parameter is fetched from the registry, and the third parameter is the main incoming value as follows:
Sc_manager_all_access (0xf003f): Default has all permissions
Sc_manager_create_service (0x0002): Has permission to create a service
Sc_manager_connect (0x0001): the right to connect
Sc_manager_enumerate_service (0x0004) Enumerate the permissions of the information inside
The following is no longer one by one explained, please see the MSDN records for more information. In the program in order to facilitate the general use of sc_manager_all_access parameters
function if the call succeeds, it returns a handle to the Operation database, and subsequent operations on the service have this parameter as the first parameter.

EnumServicesStatus: Enumerating System Services
BOOL WINAPI EnumServicesStatus(  __in          SC_HANDLE hSCManager,  __in          DWORD dwServiceType,  __in          DWORD dwServiceState,  __out         LPENUM_SERVICE_STATUS lpServices,  __in          DWORD cbBufSize,  __out         LPDWORD pcbBytesNeeded,  __out         LPDWORD lpServicesReturned,  __in_out      LPDWORD lpResumeHandle);

Hscmanager: Service database handle
Dwservicetype: Enumerates the types of services, mainly: Service_driver (driver type Service), Service_win32 (Win32 type of service)
Dwservicestate: The service that represents which state is enumerated, mainly: service_active (service started), Service_inactive (service not started), Service_state_all (all services)
Lpservices: This parameter is primarily used as a buffer to return service information, type Enum_service_status primarily stores the service name, display name, and a service_status struct, which is prototyped as follows:

typedefstruct _SERVICE_STATUS{      //服务类型    DWORD dwControlsAccepted;//当前状态    DWORD dwServiceSpecificExitCode;    DWORD dwCheckPoint;      DWORD dwWaitHint;} SERVICE_STATUS,  *LPSERVICE_STATUS;

Cbbufsize: Size of buffer
Pcbbytesneeded: Actual size of buffer required
Lpservicesreturned: Return value of the service
Lpresumehandle: Extra Handle
Each enum_service_status structure holds information about a service, but we don't know how many services we have in advance, so we don't know how much of a service information array to define, but Windows takes that into account. When the function call fails to return ERROR_MORE_DATA when using GetLastError, the supplied buffer is insufficient, this time the parameter pcbbytesneeded will return the correct size, so the use of this function will typically go through two calls for the first time lpservices = NULL, cbbufsize = 0, at this time the function is faulted and returns the actual size required, and then dynamically divided by the size of a memory buffer or provide an array, and pass in the actual size to obtain information about all services. A specific example is provided below:

Sc_handle schandle = OpenSCManager (null, NULL, sc_manager_all_access);if(NULL = = Schandle) {returnFALSE;    } lpenum_service_status pservices = NULL; DWORD Dwbyteneed =0; DWORD Dwservicereturn =0; Lpdword lpresumehandle = NULL;//First call, set the buffer to null and set the buffer size to 0BOOL BRet =:: EnumServicesStatus (Schandle, Service_win32, Service_state_all, Pservices,0, &dwbyteneed, &dwservicereturn, Lpresumehandle);if(!bret) {//If the buffer size is insufficient        if(Error_more_data = = GetLastError ()) {//Save the true size of the bufferDWORD dwrealneed = dwbyteneed;//Multiple allocation one is to save 0 of the end of the stringPservices = (lpenum_service_status)New Char[Dwrealneed +1];            ASSERT (NULL! = pservices); ZeroMemory (pservices, Dwrealneed +1); BRet =:: EnumServicesStatus (Schandle, Service_win32, Service_state_all, pservices, Dwrealneed +1, &dwbyteneed, &dwservicereturn, Lpresumehandle);//Through the above code can get information about the service}    }
Gets the path, startup type, and dependencies of the service's main program

The above code can only get some information about the system service, such as the name of the service, the display name, and so on other information needs to call another API function to get

OpenService getting a handle to a specific service
SC_HANDLE WINAPI OpenService(  __in          //服务数据库的句柄  __in          LPCTSTR lpServiceName,//服务的名称  __in          DWORD dwDesiredAccess//以何种权限打开,为了方便一般填入SERVICE_ALL_ACCESS所有权限);
QueryServiceConfig Query system service Information
BOOL WINAPI QueryServiceConfig(  __in          SC_HANDLE hService,  __out         LPQUERY_SERVICE_CONFIG lpServiceConfig,  __in          DWORD cbBufSize,  __out         LPDWORD pcbBytesNeeded);

The second parameter of this function is a struct pointer, which defines the structure as follows:

typedefstruct _QUERY_SERVICE_CONFIG {      DWORD dwServiceType;  //服务类型    DWORD dwStartType;  //启动类型    DWORD dwErrorControl;//错误码,服务执行出错时返回,操作系统根据这个错误码来做相应的处理    LPTSTR lpBinaryPathName;//主程序所在路径    LPTSTR lpLoadOrderGroup;    DWORD dwTagId;    //依赖项    LPTSTR lpServiceStartName;    //显示名称} QUERY_SERVICE_CONFIG,  *LPQUERY_SERVICE_CONFIG;

This function is called in the same way as EnumServicesStatus, and is also called by two times, the first time to obtain the required space size, this size is returned by the fourth parameter.
The following code shows how these two functions are called

///The first parameter is obtained through the OpenSCManager functionSc_handle H_scservice = OpenService (H_schandle, Psrvitem->strsrvname, service_all_access);if(NULL = = H_scservice) {Closeservicehandle (h_schandle);returnFALSE;      } lpquery_service_config psrvconfig = NULL; DWORD dwbuffsize =0; DWORD Dwbuffneed =0; BOOL BRet = QueryServiceConfig (H_scservice, Psrvconfig, dwBuffSize, &dwbuffneed);if(!bret) {if(Error_insufficient_buffer = = GetLastError ())            {DWORD dwrealneed = dwbuffneed; Psrvconfig = (lpquery_service_config)New Char[Dwrealneed +1];            ASSERT (NULL! = psrvconfig);        BRet = QueryServiceConfig (H_scservice, Psrvconfig, Dwrealneed, &dwbuffneed); }    }
Get description of the service

Descriptive information is typically provided by a service developer to interpret information such as the role of the service program, which is recorded by the system and presented to the user when it is injected into the service. The main API function used to get system services is QUERYSERVICECONFIG2

BOOL WINAPI QueryServiceConfig2(  __in          SC_HANDLE hService,  __in          DWORD dwInfoLevel,//将获取何种信息在这我们需要填写SERVICE_CONFIG_DESCRIPTION表示获取描述信息  __out         LPBYTE lpBuffer,  __in          DWORD cbBufSize,  __out         LPDWORD pcbBytesNeeded);

This function does not want to get the queryserviceconfig of the service at once, it specifies what information needs to be obtained according to the second parameter, and then returns to the buffer provided by the 3rd parameter, which is a pointer of type byte. The caller needs to type conversions based on the specific situation. The same function needs to be called two times.

BOOL BRet = QueryServiceConfig2 (H_scservice, Service_config_description, (LPBYTE) lpbyte, cbbufsize, &dwbuffneed);if(!bret) {if(Error_insufficient_buffer = = GetLastError ()) {DWORD dwrealneed = dwbuffneed;only one string pointer is saved in the//lpservice_description struct lpdescriptionLpbyte = (lpservice_description)New Char[Dwrealneed +1];            ASSERT (NULL! = lpbyte); BRet = QueryServiceConfig2 (H_scservice, Service_config_description, (LPBYTE) lpbyte, Dwrealneed, &dwbuffneed);if(!bret) {Delete[] lpbyte;Goto__error_ret; } psrvitem->strsrvdescrible = lpbyte->lpdescription;Delete[] lpbyte;            Closeservicehandle (H_scservice); Closeservicehandle (H_schandle);returnTRUE;    }}__error_ret:closeservicehandle (H_scservice); Closeservicehandle (H_schandle);returnFALSE;
Control of the service

Service Control main Control service start, pause, resume, stop and so on.

StartService Start Service
BOOL WINAPI StartService(  __in          SC_HANDLE hService,  __in          DWORD dwNumServiceArgs,//启动参数的个数  __in          LPCTSTR* lpServiceArgVectors//参数列表指针);

This function is a bit like the main function, the main function can pass the command line arguments to the program, in order to implement the program and the user's interaction, here can also pass parameters, so that the service to complete a specific function, when the second argument is 0 o'clock the third parameter is NULL

ControlService Control Services
BOOL WINAPI ControlService(  __in          SC_HANDLE hService,  __in          DWORD dwControl,//新状态  __out         LPSERVICE_STATUS lpServiceStatus//服务的原始状态);

This function is used to complete the service control except for startup, where the second parameter is the state of the service, and the parameters it can use are as follows:

Take value meaning
Service_control_continue Continue running
Service_control_pause Time out
Service_control_stop Stop it

The rest of the parts are not very common, so they are not listed here.
The following is a concrete example of how much of the code in this section is more judgmental because it takes into account the current state and whether the service supports this state.

Service_status ServiceStatus = {0};//Get the current statusBOOL BRet = QueryServiceStatus (H_scservice, &servicestatus); ASSERT (BRet);if(servicestatus.dwcurrentstate = = dwnewstatus) {Goto__return; }//If the current service is in the start and pause, but does not complete this action is not allowed to change the service state    if(servicestatus.dwcurrentstate = = Service_continue_pending | |        Service_pause_pending ==servicestatus.dwcurrentstate | | service_start_pending = = Servicestatus.dwcurrentstate | | service_stop_pending = = servicestatus.dwcurrentstate) {bRet = FALSE;Goto__return; }//If the service is in a paused state, only allow to continue running and stop    if(service_paused = = servicestatus.dwcurrentstate) {if(service_control_continue = = Dwnewstatus | | Service_control_stop = = dwnewstatus) {BRet = ControlService (H_scservice, Dwnewstatus, &servicestatu s);Goto__return; }Else{bRet = FALSE;Goto__return; }    }//If the service is running, run pause and stop    if(service_running = = servicestatus.dwcurrentstate) {if(Service_control_pause = = Dwnewstatus | | Service_control_stop = = dwnewstatus) {BRet = ControlService (H_scservice, Dwnewstatus, &servicestatu s);Goto__return; }Else{bRet = FALSE;Goto__return; }    }//If the service is in a stopped state, the operation is allowed to run    if(service_stopped = = servicestatus.dwcurrentstate) {if(service_running = = dwnewstatus) {BRet = StartService (H_scservice,0, NULL);Goto__return; }Else{bRet = FALSE;Goto__return; }}__return:if(BRet)    {piter->pnode->dwcurrentstatus = Dwnewstatus;    } closeservicehandle (H_scservice); Closeservicehandle (H_schandle);returnBRet;

The state of the current service can be obtained using the EnumServicesStatus function, but this function is to get all the service programs recorded in the system, in which case we just need to get the state of a service, call this function always have overkill meaning, So the use of another function QueryServiceStatus, the main state of the service program are as follows:

Take value Status Description
Service_running is started
service_stopped Has stopped
Service_paused Is paused
Service_continue_pending is recovering
Service_pause_pending is pausing
Service_start_pending is starting
Service_stop_pending is stopping

The first few are completed, that is, the conversion from one state to the other, while the latter is in progress, between the two states

Get the controllable type of service

When controlling a service, consider not only the current state of the service program, but also whether it supports such a state, such as a service that does not support pausing and resuming operations

QueryServiceStatus status information for a query service

This function mainly passes a pointer to a service_status struct. This structure is defined as follows:

typedefstruct _SERVICE_STATUS {    DWORD dwServiceType;//服务类型    //当前状态    DWORD dwControlsAccepted;//允许的操作    DWORD dwWin32ExitCode;    DWORD dwServiceSpecificExitCode;    DWORD dwCheckPoint;    DWORD dwWaitHint;} SERVICE_STATUS,  *LPSERVICE_STATUS;
Changing the startup type of a service

The startup type of the service mainly includes boot start, manual start, and prohibit startup. The function to change the startup type is mainly: Changeserviceconfig. The function prototypes are as follows:

BOOL WINAPI ChangeServiceConfig(  __in          SC_HANDLE hService,  __in          DWORD dwServiceType,//服务类型  __in          DWORD dwStartType,//启动类型  __in          DWORD dwErrorControl,  __in          LPCTSTR lpBinaryPathName,//服务的主程序路径  __in          LPCTSTR lpLoadOrderGroup,  __out         LPDWORD lpdwTagId,  __in          LPCTSTR lpDependencies,//依赖项  __in          LPCTSTR lpServiceStartName,//服务名称  __in          LPCTSTR lpPassword,//服务密码,主要用于控制服务  __in          LPCTSTR lpDisplayName//服务的显示名称);

The function passes all the new information of the service, if you want to change it, fill in the corresponding value, if you do not want to change the DWORD type of members to fill in service_no_change, for pointer type only need to fill in null.

Create a service

The creation service primarily uses the function CreateService, which is prototyped as follows:

Sc_handle WINAPI CreateService (__in sc_handle hscmanager, __in lpctstr lpservicename,//Service name__in LPCTSTR Lpdisplayname,//Display name__in DWORD dwDesiredAccess,//service permissions__in DWORD Dwservicetype,//Service type__in DWORD Dwstarttype,//service startup type__in DWORD Dwerrorcontrol, __in lpctstr lpbinarypathname,//Main program path__in LPCTSTR Lploadordergroup, __out lpdword lpdwtagid, __in lpctstr lpdependencies,//Dependencies__in LPCTSTR lpservicestartname, start name __in LPCTSTR Lppassword//Password); A service control manager that needs to fill in some information systems at startup to save this information, and to start the service based on some of them, some of which are required, such as the service name, which is used to uniquely identify a service, the path to the service that tells the Service Control Manager which program to start, and the dependencies, Passwords and so on can not be filled. The following is an example of the invocation of "' cppp sc_handle Hret =:: CreateService (H_scmanager, Lpservicename, Lpdisplayname, dwDesiredAccess, SERVIC E_win32_own_process, Dwstarttype, service_error_normal, lpbinarypathname, NULL, NULL, lpdependencies, LpServiceSta Rtname, Lppassword); <divclass="Se-preview-section-delimiter"></div>

Service_win32_own_process indicates that the service type is a service of the Win32 type with independent processes
Service_error_normal indicates that the error code returned by the service program is the system default error code

Delete Service

The function used by the Delete service is DeleteService, which is primarily passed to the handle of the service, which is returned by the function OpenService. It is also important to note that this function only works on services that have been stopped, so you need to stop the service before deleting it.
"'

Service_win32_own_process indicates that the service type is a service with a separate process for the Win32 type Service_error_normal indicates that the error code returned by the service program is the system default error code# # Delete ServiceThe function used by the Delete service is DeleteService, which is primarily passed to the handle of the service, which is returned by the function OpenService. It is also important to note that this function only works on services that have been stopped, so you need to stop the service before deleting it. "' CPPBOOLBRet =FALSE; DWORD Dwsrvacceptctrl = getsrvctrlaccept (piter->pnode->strsrvname);if(0= = (Dwsrvacceptctrl & service_accept_stop))//service cannot be deleted{Goto__return; }//Stop service, function Ctrlservice is the one I encapsulated before to control the service. BRet = Ctrlservice (Piter, service_control_stop);if(!bret) {Goto__return; } BRet =::D eleteservice (H_scservice);if(BRet)    {DeleteItem (Piter->pnode);    }__return:closeservicehandle (H_scservice); Closeservicehandle (H_scmanager);returnBRet;

Windows Service Management operations

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.