// Servicetest. cpp: defines the entry point for the console application.
//
# Include "stdafx. H"
# Include <winsvc. h>
# Ifdef _ debug
# Define new debug_new
# UNDEF this_file
Static char this_file [] = _ file __;
# Endif
Cwinapp theapp;
Using namespace STD;
//************************************** **************************************** *****//
// Variable Declaration
//************************************** **************************************** *****//
// Internal service name
# Define appname "dbdatabackup"
// Service display name
# Define szservicename _ T ("regular database Cleaning Service ")
// Service status
Service_status ssstatus;
// Service handle
Service_status_handle sshstatushandle;
// SC handle
SC _handle schscmanager;
SC _handle schservice;
Lpctstr * lpserviceargvectors;
// Service debugging mark
Bool bdebug = false;
// Mutex semaphores
Critical_section errcritical;
// Service exit event
Handle hsysexitevent = NULL;
//************************************** **************************************** *****//
// Function declaration
// Service entry function
Void winapi service_main (DWORD dwargc, lptstr * lpszargv );
// Service control processing functions
Void winapi service_ctrl (DWORD dwctrlcode );
// Standard error output function
Void stderrorhandler (cstring errormessage );
// Service installation Handler
Void installservice ();
// Unmount the processing function
Void removeservice ();
// Service debugging Handler
Void debugservice ();
// Write service logs
Void addtoapplog (cstring errormessage );
// Obtain the system time
Cstring getsystemtime ();
// Service start Handler
Void servicestart ();
Bool reportstatustoscmgr (DWORD dwcurrentstate, DWORD dwwin32exitcode, DWORD dwwaithint );
// Service stop Handler
Void servicestop ();
// Service pause Handler
Void servicepause ();
// Service continuation Function
Void servicecontinue ();
//************************************** **************************************** *****//
Int _ tmain (INT argc, tchar * argv [], tchar * envp [])
{
// Initialize the semaphore
Initializecriticalsection (& errcritical );
// Initialize the MFC
If (! Afxwininit (: getmodulehandle (null), null,: getcommandline (), 0 ))
{
Cerr <_ T ("Fatal error: MFC initialization failed") <Endl;
Return-1;
}
Else
{
// Register the service entry, service name, and service entry function
// The Windows execution service entry is in service_main
Service_table_entry dispatchtable [2] = {
{Szservicename, service_main },
{Null, null }};
// Obtain the Directory and file name of the current Executable File
Char exefullpath [max_path];
Getmodulefilename (null, exefullpath, max_path );
For (INT I = strlen (exefullpath); I> = 0; I --)
{
If (exefullpath [I] = '//')
{
Exefullpath [I] = 0;
Break;
}
}
// Set the current path of the current process to the service path
Setcurrentdirectory (exefullpath );
// Process command line parameters
If (argc> 1 & * argv [1] = '-')
{
// The parameter is-install to install the service.
If (_ stricmp ("Install", argv [1] + 1) = 0)
{
// Execute the installation service
Installservice ();
}
// The parameter is-Remove. Uninstall the service.
Else if (_ stricmp ("Remove", argv [1] + 1) = 0)
{
// Uninstall the service
Removeservice ();
}
// The parameter is-debug, debugging Service
Else if (_ stricmp ("debug", argv [1] + 1) = 0)
{
// Set the service debugging mark
Bdebug = true;
// Execute the debugging Service
Debugservice ();
}
Else
{
// The parameter format is invalid.
Printf ("Enter % s-install to install the service/N", appname );
Printf ("Enter % s-remove to uninstall the service/N", appname );
Printf ("Enter % s-Debug to debug the service/N", appname );
}
Exit (0 );
}
// If it does not match the preceding parameter, it may be the Service Control Manager program to start the program.
Cstring errmessage;
Printf ("/N has called startservicectrldispatcher./N ");
Printf ("This may take several seconds, please wait./N ");
// Call the startservicectrldispatcher function immediately.
If (! Startservicectrldispatcher (dispatchtable ))
{
Stderrorhandler ("failed to call startservicectrldispatcher .");
Addtoapplog (errmessage );
}
Else
{
Stderrorhandler ("startservicectrldispatcher is called successfully .");
Addtoapplog (errmessage );
}
}
Return 0;
}
//************************************** ****************//
// Service entry function
//************************************** ****************//
Void winapi service_main (DWORD dwargc, lptstr * lpszargv)
{
// Register the Service Control Handler, service appname, and control function service_ctrl
Sshstatushandle = registerservicectrlhandler (appname, service_ctrl );
// If the registration fails
If (! Sshstatushandle)
{
Cstring err;
Err = "Service Registration failed ";
Stderrorhandler (ERR );
Goto cleanup;
Return;
}
// Initialize the members in the service_status Structure
Ssstatus. dwservicetype = service_win32_own_process;
Ssstatus. dwservicespecificexitcode = 0;
// Update the service status to service_start_pending.
If (! Reportstatustoscmgr (
Service_start_pending, // service status, the service is starting.
No_error, // exit code
3000) // wait time
{
Goto cleanup; // switch to cleanup if the service status fails to be updated
}
// Start the main function of the service
Servicestart ();
Return;
Cleanup:
// Update the service status to service_stopped and exit.
If (sshstatushandle)
{
Reportstatustoscmgr (service_stopped, getlasterror (), 0 );
}
}
//************************************** ****************//
// Service control processing functions
//************************************** ****************//
Void winapi service_ctrl (DWORD dwctrlcode)
{
// Process the control request code
Switch (dwctrlcode)
{
// Update the service status to servicde_stop_pending before stopping the service.
Case service_control_stop:
{
Reportstatustoscmgr (service_stop_pending, no_error, 500 );
Servicestop (); // implemented by a specific service program
Ssstatus. dwcurrentstate = service_stopped;
Break;
}
// Suspend the service
Case service_control_pause:
{
Reportstatustoscmgr (service_stop_pending, no_error, 500 );
Servicepause (); // implemented by a specific service program
Ssstatus. dwcurrentstate = service_paused;
Break;
}
// Continue service
Case service_control_continue:
{
Reportstatustoscmgr (service_stop_pending, no_error, 500 );
Servicecontinue (); // implemented by a specific service program
Ssstatus. dwcurrentstate = service_running;
Break;
}
// Update the service status
Case service_control_interrogate:
{
Break;
}
// Invalid control code
Default:
{
Break;
}
}
// Current service status
Reportstatustoscmgr (ssstatus. dwcurrentstate, no_error, 0 );
}
//************************************** ****************//
// Service installation Handler
//************************************** ****************//
Void installservice ()
{
SC _handle schservice;
SC _handle schscmanager;
Tchar szpath [512];
Cstring err;
// Obtain the path of the program Disk File
If (getmodulefilename (null, szpath, 512) = 0)
{
Err. Format ("% s-% s/n cannot be installed", text (appname), getlasterror ());
Stderrorhandler (ERR );
Return;
}
// Open the service management database
Schscmanager = openscmanager (
Null, // Local Computer
Null, // default database
SC _manager_all_access // All access permissions are required.
);
If (schscmanager)
{
// Register the Service Program
Schservice = createservice (
Schscmanager, // service management database handle
Text (appname), // service name
Text (szservicename), // used to display the service ID
Service_all_access, // responds to all access requests
Service_win32_own_process, // service type
Service_auto_start, // start Type
Service_error_normal, // Error Control Type
Szpath, // path of the disk file of the Service Program
Null, // The service does not belong to any group
Null, // No tag identifier
Null, // start the service or service group on which the service depends. Here it is just an empty string
Null, // LocalSystem account
Null );
If (schservice)
{
Err. Format ("% s installed.", text (appname ));
Stderrorhandler (ERR );
Closeservicehandle (schservice );
}
Else
{
Err. Format ("service creation failed, service may have been installed ");
Stderrorhandler (ERR );
}
Closeservicehandle (schscmanager );
}
Else
{
Err. Format ("failed to open scmanager ");
Stderrorhandler (ERR );
}
Closeservicehandle (schscmanager );
Return;
}
//************************************** ****************//
// Unmount the processing function
//************************************** ****************//
Void removeservice ()
{
SC _handle schservice;
SC _handle schscmanager;
Cstring err;
// Open the service management database
Schscmanager = openscmanager (
Null, // Local Computer
Null, // default database
SC _manager_all_access // All access permissions are required.
);
If (schscmanager)
{
// Obtain the service program handle
Schservice = openservice (
Schscmanager, // service management database handle
Text (appname), // service name
Service_all_access // responds to all access requests
);
If (schservice)
{
// Try to stop the service
If (controlservice (
Schservice, // service program handle
Service_control_stop, // service stop Request Code
& Ssstatus // receives the final service status information
))
{
Err. Format ("Stopping % s", text (appname ));
Stderrorhandler (ERR );
Sleep (1000 );
// Wait for the service to stop
While (queryservicestatus (schservice, & ssstatus ))
{
If (service_stop_pending = ssstatus. dwcurrentstate)
{
Cout <".";
Sleep (1000 );
}
Else
{
Break;
}
}
If (service_stopped = ssstatus. dwcurrentstate)
{
Err. Format ("/n % s stopped./N", text (appname ));
Stderrorhandler (ERR );
}
Else
{
Err. Format ("/n % s trying to stop failed./N", text (appname ));
Stderrorhandler (ERR );
}
}
// Delete the installed Service Program Installation
If (deleteservice (schservice ))
{
Err. Format ("% s has been uninstalled./N", text (appname ));
Stderrorhandler (ERR );
}
Else
{
Err. Format ("failed to delete service ");
Stderrorhandler (ERR );
}
Closeservicehandle (schservice );
}
Else
{
Err. Format ("Connection Service failed, this service does not exist ");
Stderrorhandler (ERR );
}
Closeservicehandle (schscmanager );
}
Else
{
Err. Format ("failed to open scmanager ");
Stderrorhandler (ERR );
}
}
//************************************** ****************//
// Service start Handler
//************************************** ****************//
Void servicestart ()
{
// The default monitoring period is 3 minutes.
Int nwaittime = 3000;
// Report the current status to SCM
Reportstatustoscmgr (service_start_pending, no_error, 20000 );
If (! (Hsysexitevent = createevent (null, true, false, null ))){
Stderrorhandler ("service exit event creation failed ");
Return;
}
// Report the current progress and running status to SCM
Reportstatustoscmgr (service_running, no_error, 0 );
Stderrorhandler ("service started ");
Long int times = 20;
While (times)
{
Times --;
Cout <Times <",";
// Wait for the stop sign
If (waitforsingleobject (hsysexitevent, nwaittime) = wait_object_0)
{
// Notification that the SCM service is being completed
Reportstatustoscmgr (service_stop_pending, no_error, 10000 );
Stderrorhandler ("the database timed cleanup service is terminating ...");
Return;
}
Beep (1000,200 );
Sleep (nwaittime );
}
}
//************************************** ****************//
// Service stop Handler
//************************************** ****************//
Void servicestop ()
{
Setevent (hsysexitevent );
}
//************************************** ****************//
// Service pause Handler
//************************************** ****************//
Void servicepause ()
{}
//************************************** ****************//
// Service continuation Function
//************************************** ****************//
Void servicecontinue ()
{}
//************************************** ****************//
// Service log record processing function
//************************************** ****************//
Void addtoapplog (cstring errormessage)
{
}
//************************************** ****************//
// Service debugging Handler
//************************************** ****************//
Void debugservice ()
{
Servicestart ();
}
//************************************** ****************//
// Returns the current system time
//************************************** ****************//
Cstring getsystemtime ()
{
Systemtime;
Cstring timestring;
Getlocaltime (& systemtime );
Timestring. Format ("% 04d % 02d % 02d % 02d: % 02d: % 02d ",
Systemtime. wyear, systemtime. wmonth, systemtime. wday,
Systemtime. whour, systemtime. wminute, systemtime. wsecond,
Systemtime. wmilliseconds );
Return timestring;
}
/*************************************** ****************
Name: reportstatustoscmgr
Parameters:
Dwcurrentstate: current state
Dwwin32exitcode: Win32 exit code
Dwwaithint: the time that the status may last.
Return Value: bool
Function: Reports status to Service Control Manager.
**************************************** ***************/
Bool reportstatustoscmgr (DWORD dwcurrentstate,
DWORD dwwin32exitcode,
DWORD dwwaithint)
{
Static DWORD dwcheckpoint = 1;
Bool fresult = true;
If (! Bdebug ){
// If it is in the initialization status, no command is accepted
If (dwcurrentstate = service_start_pending)
Ssstatus. dwcontrolsaccepted = 0;
Else
Ssstatus. dwcontrolsaccepted = service_accept_stop;
Ssstatus. dwcurrentstate = dwcurrentstate;
Ssstatus. dwwin32exitcode = dwwin32exitcode;
Ssstatus. dwwaithint = dwwin32exitcode;
// If the status is running or stopped, the checkpoit value is 0.
If (dwcurrentstate = service_running) |
(Dwcurrentstate = service_stopped )){
Ssstatus. dwcheckpoint = 0;
Dwcheckpoint = 1;
}
Else
Ssstatus. dwcheckpoint = dwcheckpoint ++;
// Report the current status to the Service Manager
If (! (Fresult = setservicestatus (sshstatushandle, & ssstatus ))){
// Stderrorhandler (commandhandler, "failed to report status to SCM", serviceflag );
}
}
Return fresult;
}
//************************************** ****************//
// Report system errors
//************************************** ****************//
Void stderrorhandler (cstring errormessage)
{
Entercriticalsection (& errcritical );
Addtoapplog (errormessage );
Printf ("% s: % s/n", getsystemtime (), errormessage );
Leavecriticalsection (& errcritical );
}