您的位置:首页 > 编程语言 > C语言/C++

基于visual c++之windows核心编程代码分析 实现Windows服务并安装,控制

2012-12-25 14:08 766 查看
我们进行Windows编程的时候,经常涉及到Windows服务编程,针对Windows服务我们该怎么编程呢,

我们先来实现一个Windows服务并实现之,请见注释代码分析。

[cpp] view
plaincopyprint?

/* 头文件 */

#include <windows.h>

/* 全局变量 */

SERVICE_STATUS SplSrvServiceStatus;

SERVICE_STATUS_HANDLE SplSrvServiceStatusHandle;

/* 函数声明 */

VOID SvcDebugOut(LPSTR String, DWORD Status);

VOID WINAPI SplSrvServiceCtrlHandler (DWORD opcode);

VOID WINAPI SplSrvServiceStart (DWORD argc, LPTSTR *argv);

DWORD SplSrvServiceInitialization (DWORD argc, LPTSTR *argv,

DWORD *specificError);

/*************************************

* VOID WINAPI SplSrvServiceStart (DWORD argc, LPTSTR *argv)

* 功能 服务启动函数

*

* 参数 未使用

**************************************/

VOID WINAPI SplSrvServiceStart (DWORD argc, LPTSTR *argv)

{

DWORD status;

DWORD specificError;

// 填充SERVICE_STATUS 结构

SplSrvServiceStatus.dwServiceType = SERVICE_WIN32;

SplSrvServiceStatus.dwCurrentState

= SERVICE_START_PENDING; // 服务在运行

SplSrvServiceStatus.dwControlsAccepted

= SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE;

SplSrvServiceStatus.dwWin32ExitCode = 0;

SplSrvServiceStatus.dwServiceSpecificExitCode = 0;

SplSrvServiceStatus.dwCheckPoint = 0;

SplSrvServiceStatus.dwWaitHint = 0;

// 注册服务控制请求处理例程

SplSrvServiceStatusHandle = RegisterServiceCtrlHandler(

"Sample_Srv", // 服务名,在创建服务时使用了

// SERVICE_WIN32_OWN_PROCESS,因此本参数被忽略。

SplSrvServiceCtrlHandler); // 控制请求处理例程,函数名

if (SplSrvServiceStatusHandle == (SERVICE_STATUS_HANDLE)0)

{

SvcDebugOut(" [SPLSRV_SERVICE] RegisterServiceCtrlHandler "

"failed %d\n", GetLastError());

return;

}

// 初始化工作,本示例未使用,函数为空

status = SplSrvServiceInitialization(argc,argv, &specificError);

// 初始化出错,用户自行修改

if (status != NO_ERROR)

{

SplSrvServiceStatus.dwCurrentState = SERVICE_STOPPED;

SplSrvServiceStatus.dwCheckPoint = 0;

SplSrvServiceStatus.dwWaitHint = 0;

SplSrvServiceStatus.dwWin32ExitCode = status;

SplSrvServiceStatus.dwServiceSpecificExitCode = specificError;

SetServiceStatus (SplSrvServiceStatusHandle, &SplSrvServiceStatus);

return;

}

// 初始化完成,设置运行状态

SplSrvServiceStatus.dwCurrentState = SERVICE_RUNNING;

SplSrvServiceStatus.dwCheckPoint = 0;

SplSrvServiceStatus.dwWaitHint = 0;

if (!SetServiceStatus (SplSrvServiceStatusHandle, &SplSrvServiceStatus))

{

status = GetLastError();

SvcDebugOut(" [SPLSRV_SERVICE] SetServiceStatus error %ld\n",status);

}

// 用户自行修改,用于完成服务的工作

SvcDebugOut(" [SPLSRV_SERVICE] Returning the Main Thread \n",0);

return;

}

/*************************************

* DWORD SplSrvServiceInitialization(DWORD argc,

* LPTSTR *argv,

* DWORD *specificError)

* 功能 初始化,这里未进行任何工作,留待读者修改

*

* 参数

**************************************/

DWORD SplSrvServiceInitialization(DWORD argc,

LPTSTR *argv,

DWORD *specificError)

{

return(0);

}

/*************************************

* VOID WINAPI SplSrvServiceCtrlHandler (DWORD Opcode)

* 功能 服务控制请求的处理函数,与ControlService函数配合。

*

* 参数 服务控制码

**************************************/

VOID WINAPI SplSrvServiceCtrlHandler (DWORD Opcode)

{

DWORD status;

switch(Opcode)

{

case SERVICE_CONTROL_PAUSE:

// 完成相关功能

SplSrvServiceStatus.dwCurrentState = SERVICE_PAUSED;

break;

case SERVICE_CONTROL_CONTINUE:

// 完成相关功能

SplSrvServiceStatus.dwCurrentState = SERVICE_RUNNING;

break;

case SERVICE_CONTROL_STOP:

// 完成相关功能

SplSrvServiceStatus.dwWin32ExitCode = 0;

SplSrvServiceStatus.dwCurrentState = SERVICE_STOPPED;

SplSrvServiceStatus.dwCheckPoint = 0;

SplSrvServiceStatus.dwWaitHint = 0;

if (!SetServiceStatus (SplSrvServiceStatusHandle,

&SplSrvServiceStatus))

{

status = GetLastError();

SvcDebugOut(" [SPLSRV_SERVICE] SetServiceStatus error %ld\n",

status);

}

SvcDebugOut(" [SPLSRV_SERVICE] Leaving SplSrvService \n",0);

return;

case SERVICE_CONTROL_INTERROGATE:

// 收到此请求后发出声响,演示服务控制请求的处理过程,读者可自行修改

MessageBeep(MB_OK);

break;

default:

SvcDebugOut(" [SPLSRV_SERVICE] Unrecognized opcode %ld\n",

Opcode);

}

// 当前状态

if (!SetServiceStatus (SplSrvServiceStatusHandle, &SplSrvServiceStatus))

{

status = GetLastError();

SvcDebugOut(" [SPLSRV_SERVICE] SetServiceStatus error %ld\n",

status);

}

return;

}

/*************************************

* void main( )

* 功能 程序入口函数,注册服务启动函数等。

*

* 参数 服务控制码

**************************************/

void main( )

{

// 设置SERVICE_TABLE_ENTRY 数据结构,以NULL 结构结束,

// 作为StartServiceCtrlDispatcher 函数的参数。

SERVICE_TABLE_ENTRY DispatchTable[] =

{

{ "Sample_Srv", (LPSERVICE_MAIN_FUNCTION) SplSrvServiceStart },

{ NULL, NULL }

};

if (!StartServiceCtrlDispatcher( DispatchTable))

{

SvcDebugOut(" [SPLSRV_SERVICE] StartServiceCtrlDispatcher (%d)\n",

GetLastError());

}

}

/*************************************

* VOID SvcDebugOut(LPSTR String, DWORD Status)

* 功能 显示信息给调试器。

*

* 参数 LPSTR String 消息字符串

* DWORD Status 状态

**************************************/

VOID SvcDebugOut(LPSTR String, DWORD Status)

{

CHAR Buffer[1024];

if (strlen(String) < 1000)

{

wsprintf(Buffer, String, Status);

OutputDebugString(Buffer);

}

}

然后我们实现了服务以后,需要进行安装,删除服务

具体实现代码如下,请见代码分析

[cpp] view
plaincopyprint?

**************************************/

/* 头文件 */

#include <windows.h>

#include <tchar.h>

#include <stdio.h>

/* 全局变量 */

SC_HANDLE schService;

SC_HANDLE schSCManager;

LPTSTR szServiceName = TEXT("Sample_Srv");

/*************************************

* BOOL CreateSampleService(LPTSTR szPath, LPSTR szServiceName)

* 功能 创建服务

*

* 参数

* SC_HANDLE schSCManager,SCM句柄

* LPTSTR szPath, 服务程序的路径

* LPSTR szServiceName, 服务名

**************************************/

BOOL CreateSampleService(

SC_HANDLE schSCManager,

LPTSTR szPath,

LPSTR szServiceName)

{

// 创建服务

schService = CreateService(

schSCManager, // SCM 句柄

szServiceName, // 服务名

"Service sample", // 显示的服务名

SERVICE_ALL_ACCESS, // 存取权限

SERVICE_WIN32_OWN_PROCESS, // 服务类别

SERVICE_DEMAND_START, // 启动类别

SERVICE_ERROR_NORMAL, // 错误控制类别

szPath, // 服务的可执行文件路径

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());

return FALSE;

}

else

{

printf("CreateService succeeded\n");

CloseServiceHandle(schService);

return TRUE;

}

}

/*************************************

* BOOL DeleteSampleService(LPTSTR szNameOfService)

* 功能 删除服务

*

* 参数 LPTSTR szNameOfService 服务的名字

**************************************/

BOOL DeleteSampleService(LPTSTR szNameOfService)

{

schService = OpenService(

schSCManager, // SCM 句柄

szNameOfService, // 服务名

DELETE); // 可删除

if (schService == NULL)

{

printf("OpenService failed (%d)\n", GetLastError());

return FALSE;

}

// 删除服务

if (! DeleteService(schService) )

{

printf("DeleteService failed (%d)\n", GetLastError());

return FALSE;

}

else

printf("DeleteService succeeded\n");

// 关闭句柄

CloseServiceHandle(schService);

return TRUE;

}

/*************************************

* void main( int argc, TCHAR *argv[] )

* 功能 演示

*

* 参数 未使用

**************************************/

void main( int argc, TCHAR *argv[] )

{

TCHAR szBinFilePath[MAX_PATH];

PTCHAR pTemp;

DWORD dwStopError;

// 构造服务可执行程序的路径

GetModuleFileName(NULL,szBinFilePath,MAX_PATH);

pTemp = szBinFilePath+lstrlen(szBinFilePath);

while(*--pTemp!='\\');

lstrcpy(pTemp,TEXT("\\SplSrv.exe"));

// 打开 SCM

schSCManager = OpenSCManager(

NULL, // local machine

NULL, // ServicesActive database

SC_MANAGER_ALL_ACCESS); // full access rights

if (NULL == schSCManager)

printf("OpenSCManager failed (%d)\n", GetLastError());

// 创建服务

CreateSampleService(schSCManager, szBinFilePath, szServiceName);

// 启动服务

StartSampleService(schSCManager,szServiceName);

// 发送请求控制

ControlSampleService(SERVICE_CONTROL_INTERROGATE);

ControlSampleService(SERVICE_CONTROL_CONTINUE);

// 停止服务

dwStopError = StopService( schSCManager, szServiceName,

TRUE, 1000);

if(ERROR_SUCCESS == dwStopError)

{

printf("Service Stoped\n");

}

else

{

printf("Service stoped error (%u)\n",dwStopError);

}

// 删除服务

DeleteSampleService(szServiceName);

CloseServiceHandle(schSCManager);

}

然后我们如何控制服务呢,我们来实现启动、停止服务,向服务发送请求。

[cpp] view
plaincopyprint?

/* 头文件 */

#include <windows.h>

#include <tchar.h>

#include <stdio.h>

/* 全局变量 */

extern SC_HANDLE schService; // 在init.c中定义,下同

extern SC_HANDLE schSCManager;

extern LPTSTR szServiceName;

/*************************************

* BOOL StartSampleService(SC_HANDLE schSCManager,LPTSTR szServiceName)

* 功能 启动服务

*

* 参数 SC_HANDLE schSCManager SCM 句柄

* LPTSTR szServiceName 服务名

**************************************/

BOOL StartSampleService(SC_HANDLE schSCManager,LPTSTR szServiceName)

{

SC_HANDLE schService;

SERVICE_STATUS_PROCESS ssStatus;

DWORD dwOldCheckPoint;

DWORD dwStartTickCount;

DWORD dwWaitTime;

DWORD dwBytesNeeded;

// 打开服务

schService = OpenService(

schSCManager, // SCM database

szServiceName, // service name

SERVICE_ALL_ACCESS);

if (schService == NULL)

{

return 0;

}

// 启动服务

if (!StartService(

schService, // handle to service

0, // number of arguments

NULL) ) // no arguments

{

printf("Service start error (%u).\n",GetLastError());

return 0;

}

else

{

printf("Service start pending.\n");

}

// 验证状态

if (!QueryServiceStatusEx(

schService, // handle to service

SC_STATUS_PROCESS_INFO, // info level

(LPBYTE)&ssStatus, // address of structure

sizeof(SERVICE_STATUS_PROCESS), // size of structure

&dwBytesNeeded ) ) // if buffer too small

{

return 0;

}

// tick count & checkpoint.

dwStartTickCount = GetTickCount();

dwOldCheckPoint = ssStatus.dwCheckPoint;

// 查询状态,确定 PENDING 状态结束

while (ssStatus.dwCurrentState == SERVICE_START_PENDING)

{

// 等待一段时间

dwWaitTime = ssStatus.dwWaitHint / 10;

if( dwWaitTime < 1000 )

dwWaitTime = 1000;

else if ( dwWaitTime > 10000 )

dwWaitTime = 10000;

Sleep( dwWaitTime );

// 再次查询

if (!QueryServiceStatusEx(

schService, // handle to service

SC_STATUS_PROCESS_INFO, // info level

(LPBYTE)&ssStatus, // address of structure

sizeof(SERVICE_STATUS_PROCESS), // size of structure

&dwBytesNeeded ) ) // if buffer too small

break;

if ( ssStatus.dwCheckPoint > dwOldCheckPoint )

{

// 进程创建中

dwStartTickCount = GetTickCount();

dwOldCheckPoint = ssStatus.dwCheckPoint;

}

else

{

if(GetTickCount()-dwStartTickCount > ssStatus.dwWaitHint)

{

// WaitHint 时间到

break;

}

}

}

// 关闭句柄

CloseServiceHandle(schService);

// 判断是否创建成功(状态由PENDING变为RUNNING)

if (ssStatus.dwCurrentState == SERVICE_RUNNING)

{

printf("StartService SUCCESS.\n");

return 1;

}

else

{

printf("\nService not started. \n");

printf(" Current State: %d\n", ssStatus.dwCurrentState);

printf(" Exit Code: %d\n", ssStatus.dwWin32ExitCode);

printf(" Service Specific Exit Code: %d\n",

ssStatus.dwServiceSpecificExitCode);

printf(" Check Point: %d\n", ssStatus.dwCheckPoint);

printf(" Wait Hint: %d\n", ssStatus.dwWaitHint);

return 0;

}

}

/*************************************

* DWORD StopService( SC_HANDLE hSCM,

LPTSTR szServiceName,

BOOL fStopDependencies,

DWORD dwTimeout )

* 功能 停止服务

*

* 参数 SC_HANDLE hSCM SCM 句柄

* LPTSTR szServiceName 服务名

* BOOL fStopDependencies 是否结束依赖的服务

* DWORD dwTimeout 超时

**************************************/

DWORD StopService(SC_HANDLE hSCM,

LPTSTR szServiceName,

BOOL fStopDependencies,

DWORD dwTimeout )

{

SERVICE_STATUS_PROCESS ssp;

SERVICE_STATUS ss;

DWORD dwStartTime = GetTickCount();

DWORD dwBytesNeeded;

// 打开服务

SC_HANDLE hService = OpenService(

hSCM, // SCM 句柄

szServiceName, // 服务名

SERVICE_ALL_ACCESS);

// 查询状态,确定是否已经停止

if ( !QueryServiceStatusEx(

hService,

SC_STATUS_PROCESS_INFO,

(LPBYTE)&ssp,

sizeof(SERVICE_STATUS_PROCESS),

&dwBytesNeeded ) )

{

return GetLastError();

}

if ( ssp.dwCurrentState == SERVICE_STOPPED )

{

return ERROR_SUCCESS;

}

// 如果是 STOP_PENDING 状态,则只需等待

while ( ssp.dwCurrentState == SERVICE_STOP_PENDING )

{

Sleep( ssp.dwWaitHint );

// 循环查询,直到状态改变

if ( !QueryServiceStatusEx(

hService,

SC_STATUS_PROCESS_INFO,

(LPBYTE)&ssp,

sizeof(SERVICE_STATUS_PROCESS),

&dwBytesNeeded ) )

{

return GetLastError();

}

if ( ssp.dwCurrentState == SERVICE_STOPPED )

{

return ERROR_SUCCESS;

}

if ( GetTickCount() - dwStartTime > dwTimeout )

{

return ERROR_TIMEOUT;

}

}

// 先结束依赖服务

if ( fStopDependencies )

{

DWORD i;

DWORD dwBytesNeeded;

DWORD dwCount;

LPENUM_SERVICE_STATUS lpDependencies = NULL;

ENUM_SERVICE_STATUS ess;

SC_HANDLE hDepService;

// 使用 0 大小的 buf,获取buf的大小

// 如果 EnumDependentServices 直接返回成功,说明没有依赖服务

if ( !EnumDependentServices( hService, SERVICE_ACTIVE,

lpDependencies, 0, &dwBytesNeeded, &dwCount ) )

{

if ( GetLastError() != ERROR_MORE_DATA )

return GetLastError(); // Unexpected error

// 分配缓冲区存储依赖服务的数据

lpDependencies = (LPENUM_SERVICE_STATUS) HeapAlloc(

GetProcessHeap(), HEAP_ZERO_MEMORY, dwBytesNeeded );

if ( !lpDependencies )

return GetLastError();

__try {

// 获得依赖服务

if ( !EnumDependentServices( hService, SERVICE_ACTIVE,

lpDependencies, dwBytesNeeded, &dwBytesNeeded,

&dwCount ) )

return GetLastError();

for ( i = 0; i < dwCount; i++ )

{

ess = *(lpDependencies + i);

// 打开服务

hDepService = OpenService( hSCM, ess.lpServiceName,

SERVICE_STOP | SERVICE_QUERY_STATUS );

if ( !hDepService )

return GetLastError();

__try {

// 结束服务

if ( !ControlService( hDepService,

SERVICE_CONTROL_STOP,

&ss ) )

return GetLastError();

// 等待服务结束

while ( ss.dwCurrentState != SERVICE_STOPPED )

{

Sleep( ss.dwWaitHint );

if ( !QueryServiceStatusEx(

hDepService,

SC_STATUS_PROCESS_INFO,

(LPBYTE)&ssp,

sizeof(SERVICE_STATUS_PROCESS),

&dwBytesNeeded ) )

return GetLastError();

if ( ss.dwCurrentState == SERVICE_STOPPED )

break;

if ( GetTickCount() - dwStartTime > dwTimeout )

return ERROR_TIMEOUT;

}

}

__finally

{

// 关闭服务

CloseServiceHandle( hDepService );

}

}

}

__finally

{

// 释放内存

HeapFree( GetProcessHeap(), 0, lpDependencies );

}

}

}

// 所有的依赖服务已经结束,结束指定服务

if ( !ControlService( hService, SERVICE_CONTROL_STOP, &ss ) )

return GetLastError();

while ( ss.dwCurrentState != SERVICE_STOPPED )

{

Sleep( ss.dwWaitHint );

if ( !QueryServiceStatusEx(

hService,

SC_STATUS_PROCESS_INFO,

(LPBYTE)&ssp,

sizeof(SERVICE_STATUS_PROCESS),

&dwBytesNeeded ) )

return GetLastError();

if ( ss.dwCurrentState == SERVICE_STOPPED )

break;

if ( GetTickCount() - dwStartTime > dwTimeout )

return ERROR_TIMEOUT;

}

return ERROR_SUCCESS;

}

/*************************************

* BOOL ControlSampleService(DWORD fdwControl)

* 功能 向服务发送控制码

*

* 参数 DWORD fdwControl 控制码值

* SCM 句柄,服务名直接使用全局变量

**************************************/

BOOL ControlSampleService(DWORD fdwControl)

{

SERVICE_STATUS ssStatus;

DWORD fdwAccess;

DWORD dwStartTickCount, dwWaitTime;

// Access

switch (fdwControl)

{

case SERVICE_CONTROL_STOP:

fdwAccess = SERVICE_STOP;

break;

case SERVICE_CONTROL_PAUSE:

case SERVICE_CONTROL_CONTINUE:

fdwAccess = SERVICE_PAUSE_CONTINUE;

break;

case SERVICE_CONTROL_INTERROGATE:

fdwAccess = SERVICE_INTERROGATE;

break;

default:

fdwAccess = SERVICE_INTERROGATE;

}

// 打开服务

schService = OpenService(

schSCManager, // SCManager 句柄

szServiceName, // 服务名

fdwAccess); // 存取权限

if (schService == NULL)

{

printf("OpenService failed (%d)\n", GetLastError());

return FALSE;

}

// 发送控制码

if (! ControlService(

schService, // 服务的句柄

fdwControl, // 控制码

&ssStatus) ) // 状态

{

printf("ControlService failed (%d)\n", GetLastError());

return FALSE;

}

// 显示状态

printf("\nStatus of Sample_Srv: \n");

printf(" Service Type: 0x%x\n", ssStatus.dwServiceType);

printf(" Current State: 0x%x\n", ssStatus.dwCurrentState);

printf(" Controls Accepted: 0x%x\n",

ssStatus.dwControlsAccepted);

printf(" Exit Code: %d\n", ssStatus.dwWin32ExitCode);

printf(" Service Specific Exit Code: %d\n",

ssStatus.dwServiceSpecificExitCode);

printf(" Check Point: %d\n", ssStatus.dwCheckPoint);

printf(" Wait Hint: %d\n", ssStatus.dwWaitHint);

return TRUE;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐