需要实现这么一个功能:windows系统开机时启动某个进程,当发现这个进程被关闭时,要再次启动它。然后就想到了用windows服务刚好合适呀。
创建工程
用Visual Studio创建一个控制台程序就行,然后在main.cpp添加两个空函数,一个函数叫installService,另一个函数叫uninstallService。
安装服务
打开服务管理器 --> 创建服务 --> 修改服务配置 --> 清理资源
// 服务名称
#define SERVICE_NAME L"SimpleService"
#define SERVICE_DISPLAY_NAME L"简单服务示例"
// 安装服务
voidinstallService()
{
// 打开服务控制管理器
SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
if (hSCManager)
{
// 获取当前路径
wchar_t szPath[MAX_PATH];
GetModuleFileName(NULL, szPath, MAX_PATH);
// 创建服务
SC_HANDLE hService = CreateService(
hSCManager,
SERVICE_NAME,
SERVICE_DISPLAY_NAME,
SERVICE_ALL_ACCESS,
SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START,
SERVICE_ERROR_NORMAL,
szPath,
NULL, NULL, NULL, NULL, NULL);
// 清理打开的资源
if (hService)
{
//添加描述
SERVICE_DESCRIPTION sd = { 0 };
sd.lpDescription = (LPWSTR)L"这仅仅是个测试服务,没啥用。";
if (!ChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, &sd))
{
wprintf(L"设置服务描述失败,错误: %lu\n", GetLastError());
}
//设置延迟启动
SERVICE_DELAYED_AUTO_START_INFO delayedInfo = { TRUE };
if (!ChangeServiceConfig2(hService, SERVICE_CONFIG_DELAYED_AUTO_START_INFO, &delayedInfo))
{
wprintf(L"设置服务延迟启动失败,错误: %lu\n", GetLastError());
}
wprintf(L"服务安装成功!\n");
CloseServiceHandle(hService);
}
else
{
wprintf(L"服务安装失败,错误码: %d\n", GetLastError());
}
CloseServiceHandle(hSCManager);
}
}OpenSCManager
打开服务控制管理器
SC_HANDLE OpenSCManagerA(
[in, optional] LPCSTR lpMachineName,
[in, optional] LPCSTR lpDatabaseName,
[in] DWORD dwDesiredAccess
);第一个参数lpMachineName: 目标计算机的名称,NULL表示本机
第二个参数lpDatabaseName: 服务管理控制器数据库的名称,NULL表示当前活动的数据库
第三个参数dwDesiredAccess: 指定访问权限。SC_MANAGER_ALL_ACCESS是所有权限,安装服务仅指定SC_MANAGER_CREATE_SERVICE就足够了
CreateService
创建服务并添加到服务管理控制器数据库中。
SC_HANDLE CreateServiceA(
[in] SC_HANDLE hSCManager,
[in] LPCSTR lpServiceName,
[in, optional] LPCSTR lpDisplayName,
[in] DWORD dwDesiredAccess,
[in] DWORD dwServiceType,
[in] DWORD dwStartType,
[in] DWORD dwErrorControl,
[in, optional] LPCSTR lpBinaryPathName,
[in, optional] LPCSTR lpLoadOrderGroup,
[out, optional] LPDWORD lpdwTagId,
[in, optional] LPCSTR lpDependencies,
[in, optional] LPCSTR lpServiceStartName,
[in, optional] LPCSTR lpPassword
);很多参数哈!一个个来看看
第一个hSCManager:服务管理器
第二个lpServiceName:安装的服务名称
第三个lpDisplayName:用来对外显示服务名称。
第四个dwDesiredAccess:对服务的访问权限,无特殊要求就设置SC_MANAGER_ALL_ACCESS
第五个dwServiceType:服务类型,可以设置文件系统驱动程序服务、驱动程序服务、进程服务、共享进程服务。
第六个dwStartType:服务启动选项,SERVICE_AUTO_START自动启动
第七个dwErrorControl:服务无法启动的处理,SERVICE_ERROR_NORMAL把错误记录到事件日志中。
第八个lpBinaryPathName:服务程序的路径
第九个lpLoadOrderGroup:此服务所属的加载排序组,NULL:不属于任何组
第十个lpdwTagId:返回此服务在加载排序组的唯一标志
第十一个lpDependencies:指定组依赖项,NULL:没有依赖项
第十二个lpServiceStartName:运行服务的账户名称,NULL:本地SYSTEM账户
第十三个lpPassword:运行服务的账户密码,NULL:没有密码。
ChangeServiceConfig2
修复服务配置参数
BOOL ChangeServiceConfig2(
[in] SC_HANDLE hService,
[in] DWORD dwInfoLevel,
[in, optional] LPVOID lpInfo
);第一个hService: 服务句柄
第二个dwInfoLevel:指定要修改的配置,SERVICE_CONFIG_DESCRIPTION:修改描述信息;SERVICE_CONFIG_DELAYED_AUTO_START_INFO:设置延迟启动。
第三个lpInfo:取决于第二个参数
卸载服务
打开服务管理器 --> 打开已安装的服务 --> 停止服务 --> 删除服务 --> 清理资源
voiduninstallService()
{
SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (hSCManager)
{
SC_HANDLE hService = OpenService(hSCManager, SERVICE_NAME, SERVICE_STOP | DELETE);
if (hService)
{
SERVICE_STATUS status;
ControlService(hService, SERVICE_CONTROL_STOP, &status);
DeleteService(hService);
wprintf(L"服务卸载成功!\n");
CloseServiceHandle(hService);
}
else
{
wprintf(L"服务卸载失败,错误码: %d\n", GetLastError());
}
CloseServiceHandle(hSCManager);
}
}OpenService
打开服务
SC_HANDLE OpenServiceA(
[in] SC_HANDLE hSCManager,
[in] LPCSTR lpServiceName,
[in] DWORD dwDesiredAccess
);第一个hSCManager:服务管理器
第二个lpServiceName:服务名称
第三个dwDesiredAccess:权限 SERVICE_STOP:停止服务;DELETE:删除服务。
ControlService
控制代码发送给服务
BOOL ControlService(
[in] SC_HANDLE hService,
[in] DWORD dwControl,
[out] LPSERVICE_STATUS lpServiceStatus
);第一个hService:服务句柄
第二个dwControl:控制代码,SERVICE_CONTROL_STOP:通知服务停止
第三个lpServiceStatus:接收服务状态信息
返回值:失败返回0,成功返回非0。
typedefstruct_SERVICE_STATUS {
DWORD dwServiceType;
DWORD dwCurrentState;
DWORD dwControlsAccepted;
DWORD dwWin32ExitCode;
DWORD dwServiceSpecificExitCode;
DWORD dwCheckPoint;
DWORD dwWaitHint;
} SERVICE_STATUS, *LPSERVICE_STATUS;第二个dwCurrentState:服务的当前状态。
DeleteService
删除服务
BOOL DeleteService(
[in] SC_HANDLE hService
);第一个hService: 服务句柄,必须要有DELETE权限。
调用安装和卸载
intwmain(int argc, wchar_t* argv[])
{
// 检查是否是安装/卸载命令
if (argc > 1)
{
if (_wcsicmp(argv[1], L"install") == 0)
{
installService();
}
elseif (_wcsicmp(argv[1], L"uninstall") == 0)
{
uninstallService();
}
return0;
}
//入口函数...
return0;
}测试安装
打开命令行,切换到进程所在目录,执行SimpleServer.exe install
打开服务面板可以看到服务已经安装上了。


但是还无法启动,因为服务的入口函数没有指定。
测试卸载
在命令行中再执行SimpleServer.exe uninstall
刷新服务面板,可以看到服务又没了。
(关于windows API接口,本篇仅大致说明参数的用途,详细内容还请参阅官方文档。)
夜雨聆风