Example: A Service Control Shell
Services are frequently controlled from the Administrative Tools, where there is a "Services" icon. Alternatively, you can control user-developed services using ServiceShell (Chapter 6's JobShell (Program 6-3).
Program 13-3. ServiceShell: A Service Control Program
/* Chapter 13. */
/* ServiceShell.c Windows service management shell program.
This program modifies Chapter 6's job management program,
managing services rather than jobs. */
/* Commands supported are:
create -- create a service
delete -- delete a service
start -- start a service
control -- control a service */
#include "EvryThng.h"
static SC_HANDLE hScm;
static BOOL Debug;
int _tmain (int argc, LPTSTR argv [])
{
BOOL Exit = FALSE;
TCHAR Command [MAX_COMMAND_LINE + 10], *pc;
DWORD i, LocArgc; /* Local argc. */
TCHAR argstr [MAX_ARG] [MAX_COMMAND_LINE];
LPTSTR pArgs [MAX_ARG];
/* Prepare the local "argv" array as pointers to strings. */
for (i = 0; i < MAX_ARG; i++) pArgs [i] = argstr [i];
/* Open the SC Control Manager on the local machine. */
hScm = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS);
/* Main command processing loop. */
_tprintf (_T ("\nWindows Service Management"));
while (!Exit) {
_tprintf (_T ("\nSM$"));
_fgetts (Command, MAX_COMMAND_LINE, stdin);
... Similar to JobShell ...
if (_tcscmp (argstr [0], _T ("create")) == 0) {
Create (LocArgc, pArgs, Command);
}
... Similarly for all commands ...
}
CloseServiceHandle (hScm);
return 0;
}
int Create (int argc, LPTSTR argv [], LPTSTR Command)
{
/* Create a new service as a "demand start" service:
argv [1]: service Name
argv [2]: display Name
argv [3]: binary executable */
SC_HANDLE hSc;
TCHAR CurrentDir [MAX_PATH + 1], Executable [MAX_PATH + 1];
hSc = CreateService (hScm, argv [1], argv [2],
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
Executable, NULL, NULL, NULL, NULL, NULL);
return 0;
}
/* Delete a service -- argv [1]: ServiceName to delete. */
int Delete (int argc, LPTSTR argv [], LPTSTR Command)
{
SC_HANDLE hSc;
hSc = OpenService (hScm, argv [1], DELETE);
DeleteService (hSc);
CloseServiceHandle (hSc);
return 0;
}
/* Start a named service -- argv [1]: service name to start. */
int Start (int argc, LPTSTR argv [], LPTSTR Command)
{
SC_HANDLE hSc;
TCHAR WorkingDir [MAX_PATH + 1];
LPTSTR pWorkingDir = WorkingDir;
LPTSTR argvStart [] = {argv [1], WorkingDir};
GetCurrentDirectory (MAX_PATH + 1, WorkingDir);
hSc = OpenService(hScm, argv [1], SERVICE_ALL_ACCESS);
/* Start the service with one arg, the working directory. */
/* Note: The service name agrees, by default, with the name */
/* associated with the handle, hSc, by OpenService. */
/* But, the ServiceMain function does not verify this. */
StartService (hSc, 2, argvStart);
CloseServiceHandle (hSc);
return 0;
}
/* Control a named service. argv [1]: service name to control.
argv [2]: Control command: stop, pause, resume, interrogate. */
static LPCTSTR Commands [] =
{"stop," "pause," "resume," "interrogate," "user"};
static DWORD Controls [] = {
SERVICE_CONTROL_STOP, SERVICE_CONTROL_PAUSE,
SERVICE_CONTROL_CONTINUE, SERVICE_CONTROL_INTERROGATE, 128};
int Control (int argc, LPTSTR argv [], LPTSTR Command)
{
SC_HANDLE hSc;
SERVICE_STATUS ServiceStatus;
DWORD dwControl, i;
BOOL Found = FALSE;
for (i= 0; i < sizeof (Controls)/sizeof (DWORD) && !Found; i++)
Found = (_tcscmp (Commands [i], argv [2]) == 0);
if (!Found) {
_tprintf (_T ("\nIllegal Control Command %s"), argv [1]);
return 1;
}
dwControl = Controls [i - 1];
hSc = OpenService(hScm, argv [1],
SERVICE_INTERROGATE | SERVICE_PAUSE_CONTINUE |
SERVICE_STOP | SERVICE_USER_DEFINED_CONTROL |
SERVICE_QUERY_STATUS);
ControlService (hSc, dwControl, &ServiceStatus);
if (dwControl == SERVICE_CONTROL_INTERROGATE) {
QueryServiceStatus (hSc, &ServiceStatus);
printf (_T ("Status from QueryServiceStatus\n"));
printf (_T ("Service Status\n"));
... Print all other status information ...
}
if (hSc != NULL) CloseServiceHandle (hSc);
return 0;
}