window服务调试(一):winodw服务运行原理
windows服务运行主要由三部分构成:安装windows服务 启动windows服务 卸载windows服务
一、安装window服务
安装window服务的原理是获取到SCM(服务控制管理器)的句柄,然后将服务名和该服务的可执行路径写入SCM中以注册一个服务,用到的Windows API有 OpenSCManager、CreateService
示例代码:
VOID SvcInstall()
{
SC_HANDLE schSCManager;
SC_HANDLE schService;
TCHAR szPath[MAX_PATH];
if (!GetModuleFileName(NULL, szPath, MAX_PATH))
{
printf("Cannot install service (%d)\n", GetLastError());
return;
}
// Get a handle to the SCM database.
schSCManager = OpenSCManager(
NULL, // local computer
NULL, // ServicesActive database
SC_MANAGER_ALL_ACCESS); // full access rights
if (NULL == schSCManager)
{
printf("OpenSCManager failed (%d)\n", GetLastError());
return;
}
// Create the service
schService = CreateService(
schSCManager, // SCM database
SVCNAME, // name of service
SVCNAME, // service name to display
SERVICE_ALL_ACCESS, // desired access
SERVICE_WIN32_OWN_PROCESS, // service type
SERVICE_DEMAND_START, // start type
SERVICE_ERROR_NORMAL, // error control type
szPath, // path to service‘s binary
NULL, // no load ordering group
NULL, // no tag identifier
NULL, // no dependencies
NULL, // LocalSystem account
NULL); // no password
if (schService == NULL)
{
printf("CreateService failed (%d)\n", GetLastError());
CloseServiceHandle(schSCManager);
return;
}
else printf("Service installed successfully\n");
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
}
启动window服务
winodw服务并不是服务程序启动的,而是由SCM启动的,如下图所示( 按win+R 输入services.msc即可打开服务)当你启动这个服务时,SCM就会按照之前安装服务给出的路径去启动服务程序
这个时候
1.你需要告诉SCM主要的服务函数在哪里,然后SCM就会调用这个函(StartServiceCtrlDispatcher)
2.用一个回调函数处理当SCM停止服务、暂停服务、恢复服务要做哪些操作(RegisterServiceCtrlHandler)
3.最后在主要的服务函数中告诉SCM启动成功(setSvcStatus或ReportSvcStatus)
示例代码
{
// If command-line parameter is "install", install the service.
// Otherwise, the service is probably being started by the SCM.
if (lstrcmpi(argv[1], TEXT("install")) == 0)
{
SvcInstall();
return;
}
// TO_DO: Add any additional services for the process to this table.
SERVICE_TABLE_ENTRY DispatchTable[] =
{
{ SVCNAME, (LPSERVICE_MAIN_FUNCTION)SvcMain },
{ NULL, NULL }
};
DWORD dw_RetCode = -1;
// This call returns when the service has stopped.
// The process should simply terminate when the call returns.
if (!StartServiceCtrlDispatcher(DispatchTable))
{
dw_RetCode = GetLastError();
MessageBoxEx(NULL, _T("start SvrName service fail!"), NULL, 0, 0);
SvcReportEvent(TEXT("StartServiceCtrlDispatcher"));
}
}
VOID WINAPI SvcMain(DWORD dwArgc, LPTSTR *lpszArgv)
{
// Register the handler function for the service
gSvcStatusHandle = RegisterServiceCtrlHandler(
SVCNAME,
SvcCtrlHandler);
if (!gSvcStatusHandle)
{
SvcReportEvent(TEXT("RegisterServiceCtrlHandler"));
return;
}
// These SERVICE_STATUS members remain as set here
gSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
gSvcStatus.dwServiceSpecificExitCode = 0;
gSvcStatus.dwControlsAccepted = SERVICE_ACCEPT_PAUSE_CONTINUE;
WriteToLog("in SvrMain(), start Service success!");
// Report initial status to the SCM
ReportSvcStatus(SERVICE_START_PENDING, NO_ERROR, 3000);
// Perform service-specific initialization and work.
SvcInit(dwArgc, lpszArgv);
}```
#### 卸载window服务
##### 卸载Window服务是最简单的,利用OpenSCManager和OpenService获取服务句柄,再用DeleteService删除服务即可