如何编写NT服务? a class to wrap this 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 Windows NT 下Service 的 编 程 ---- Windows NT Server 提 供 多 种 功 能 强 大 的 服 务(Service), 例 如FTP,WWW 或 远 程 登 录 服 务, 另 外 常 用 的 数 据 库 服 务 器 也 是 以Service 的 形 式 存 在 于NT Server 上 的, 如Sybase SQL Server For NT。Service 一 般 在NT 启 动 时 自 动 启 动, 在NT 关 机 时 停 止。 但 是 有 时 用 户 可 能 想 手 工 启 动﹑ 暂 停﹑ 停 止 某 项Service, 这 就 需 要 在 控 制 面 板 中 进 行 配 置, 对 于 不 太 熟 悉NT 的 用 户 来 说 比 较 困 难; 对 于 软 件 开 发 人 员, 有 时 需 要 在 软 件 中 访 问 和 操 作 某 项Service, 甚 至 可 能 需 要 开 发 新Service 的 提 供 给 用 户 使 用。 上 面 两 种 情 况 都 可 以 通 过 对Service 的 编 程 来 解 决。 对Service 的 编 程 涉 及 到NT 的 内 核, 比 较 复 杂 且 相 关 资 料 较 少, 给 软 件 开 发 人 员 带 来 很 多 困 难, 笔 者 通 过 对Windows NT 的API 的 分 析 找 到 了 相 应 的 编 程 方 法, 再 此 介 绍 给 大 家。 ---- 在Windows NT 下, 各 种Service 都 存 在service control manager database 中, 因 此 我 们 可 以 通 过 对service control manager database 进 行 操 作 来 实 现 对Service 的 编 程。 下 面 介 绍 常 用 的 函 数: 1:SC_HANDLE OpenSCManager (LPCTSTR lpszMachineName, LPCTSTR lpszDatabaseName, DWORD fdwDesiredAccess); ---- OpenSCManager 函 数 打 开 指 定 计 算 机 上 的service control manager database 。 其 中 参 数lpszMachineName 指 定 计 算 机 名, 若 为 空 则 指 定 为 本 机。 参 数lpszDatabaseName 指 定 要 打 开 的service control manager database, 默 认 为 空。 ---- 参 数fdwDesiredAccess 指 定 操 作 的 权 限, 可 以 为 下 面 取 值 之 一 SC_MANAGER_ALL_ACCESS //所有权限 SC_MANAGER_CONNECT //允许连接service control manager SC_MANAGER_CREATE_SERVICE //允许创建服务对象并把它加入 service control manager database SC_MANAGER_ENUMERATE_SERVICE //允许枚举service control manager database中的服务 SC_MANAGER_LOCK //允许锁住service control manager database SC_MANAGER_QUERY_LOCK_STATUS //允许获取service control manager database的封锁信息---- 函 数 返 回 值: 函 数 执 行 成 功 则 返 回 一 个 指 向service control manager database 的 句 柄, 失 败 则 返 回NULL。 2:SC_HANDLE OpenService (SC_HANDLE schSCManager, LPCTSTR lpszServiceName, DWORD fdwDesiredAccess);---- OpenService 函 数 打 开 指 定 的Service。 ---- 其 中 参 数schSCManager 是 指 向service control manager database 的 句 柄, 由OpenSCManager 函 数 返 回。 ---- 参 数lpszServiceName 要 打 开 的 服 务 的 名 字, 注 意 大 小 写。 ---- 参 数fdwDesiredAccess 指 定 操 作 的 权 限, 可 以 为 下 面 取 值 之 一 SERVICE_ALL_ACCESS //所有权限 SERVICE_CHANGE_CONFIG //允许更改服务的配置 SERVICE_ENUMERATE_DEPENDENTS //允许获取依赖于该服务的其他服务 SERVICE_INTERROGATE //允许立即获取服务状态 SERVICE_PAUSE_CONTINUE //允许暂停和唤醒服务 SERVICE_QUERY_CONFIG //允许获取服务配置 SERVICE_QUERY_STATU //允许通过访问service control manager获取服务状态 SERVICE_START //允许启动服务 SERVICE_STOP //允许停止服务 SERVICE_USER_DEFINE_CONTROL//允许用户指定特殊的服务控制码---- 函 数 返 回 值: 函 数 执 行 成 功 则 返 回 指 向 某 项 服 务 的 句 柄, 失 败 则 返 回NULL。 3:BOOL QueryServiceStatus (SC_HANDLE schService, LPSERVICE_STATUS lpssServiceStatus);---- QueryServiceStatus函数返回指定服务的当前状态。 ---- 其中参数schService是指向某项服务的句柄,由OpenService函数返回,且必须SERVICE_QUERY_STATUS的权限。 ---- 参数lpssServiceStatus中存放返回的服务状态信息,结构如下 typedef struct _SERVICE_STATUS { DWORD dwServiceType; //服务类型DWORD dwCurrentState; //当前状态DWORD dwControlsAccepted; //服务可接受的控制码DWORD dwWin32ExitCode; //Win32出错代码DWORD dwServiceSpecificExitCode; //服务出错代码DWORD dwCheckPoint; //用于跟踪服务长时间操作DWORD dwWaitHint; //服务某一操作的最大允许时间,以毫秒为单位} SERVICE_STATUS, *LPSERVICE_STATUS; ---- 函 数 返 回 值: 函 数 执 行 成 功 则 返 回True, 失 败 则 返 回False。 4:BOOL StartService(SC_HANDLE schService, DWORD dwNumServiceArgs, LPCTSTR *lpszServiceArgs);---- StartService 函 数 启 动 指 定 的 服 务。 ---- 其 中 参 数schService 是 指 向 某 项 服 务 的 句 柄, 由OpenService 函 数 返 回, 且 必 须 有SERVICE_START 的 权 限。 ---- dwNumServiceArgs 为 启 动 服 务 所 需 的 参 数 的 个 数。 ---- lpszServiceArgs 为 启 动 服 务 所 需 的 参 数。 函 数 返 回 值: 函 数 执 行 成 功 则 返 回True, 失 败 则 返 回False。 5:BOOL ControlService( SC_HANDLE hService, DWORD dwControl, LPSERVICE_STATUS lpServiceStatus);---- ControlService 函 数 向Win32 service 发 送 控 制 码。 ---- 其 中 参 数hService 是 指 向 某 项 服 务 的 句 柄, 由OpenService 函 数 返 回。 ---- 参 数dwControl 为 控 制 码, 常 用 的 有 SERVICE_CONTROL_STOP //停止服务SERVICE_CONTROL_PAUSE //暂停服务SERVICE_CONTROL_CONTINUE //唤醒暂停的服务 SERVICE_CONTROL_INTERROGATE //刷新某服务的状态---- 参 数lpServiceStatus 指 向SERVICE_STATUS 结 构, 用 于 存 放 该 服 务 最 新 的 状 态 信 息。 ---- 函 数 返 回 值: 函 数 执 行 成 功 则 返 回True, 失 败 则 返 回False。 6:BOOL EnumServicesStatus (SC_HANDLE hSCManager, DWORD dwServiceType, DWORD dwServiceState, LPENUM_SERVICE_STATUS lpServices, DWORD cbBufSize, LPDWORD pcbBytesNeeded, LPDWORD lpServicesReturned, LPDWORD lpResumeHandle);---- EnumServicesStatus 函 数 用 于 枚 举NT 下 存 在 的Service。 ---- 其 中 参 数hSCManager 是 指 向service control manager database 的 句 柄, 由OpenSCManager 函 数 返 回, 且 必 须 有SC_MANAGER_ENUMERATE_SERVICE 的 权 限。 ---- 参 数dwServiceType 指 定 按 服 务 的 类 型 枚 举。 ---- 参 数dwServiceState 指 定 按 服 务 的 状 态 枚 举。 ---- 参 数lpServices 指 向ENUM_SERVICE_STATUS 结 构, 用 于 存 放 返 回 的 服 务 的 名 字 和 状 态 信 息。 ---- 参 数cbBufSize 返 回 参 数lpServices 的 长 度, 以 字 节 为 单 位。 ---- 参 数pcbBytesNeeded 返 回 获 取 剩 余 的Service 所 需 字 节 的 个 数。 ---- 参 数lpServicesReturned 返 回 服 务 的 个 数。 ---- 参 数lpResumeHandle, 当 第 一 次 调 用 时 该 参 数 为0, 当 该 函 数 再 次 被 调 用 以 获 取 另 外 的 信 息 时, 该 参 数 表 示 下 一 个 被 读 的Service。 ---- 函 数 返 回 值: 函 数 执 行 成 功 则 返 回True, 失 败 则 返 回False。 ---- 值 得 注 意 的 是 通 常 情 况 下 该 函 数 返 回 的 结 果 为FALSE, 我 们 可 以 调 用GetLastError() 来 获 取 进 一 步 信 息。 因 为 一 台 机 器 上 有 多 种 服 务 存 在, 所 以GetLastError() 应 为ERROR_MORE_DATA, 此 时 应 再 次 调 用EnumServicesStatus 函 数 以 获 取 正 确 的Service 列 表。 我介紹一種簡單的方法;1.用vc->NEW->ATL Com APPWizard->Service不寫代碼即可生成一什麼都不干的NT Service程序,2.安裝;NT下Run 你的應用程序 /SERVICE即可在這外殼內再加入你的代碼很簡單 用ATL哪简单了,至少要搞懂ATL就很不简单 原理有些复杂。请参考[美]Mikey Williams编写,前导工作室翻译,机械工业出版社出版的《Windows 2000编程技术内幕》ISBN:7-111-07632-X/TP.1271 FireAngel你好,随时可见你的踪影,我想问一下,如何编写有界面的Service程序,MSDN里好象没有这方面的例程,虽然文档中好象也讲过可以编写用户界面的Service另外你这么辛苦好象有点不太值吧,我看你回答了不少问题,而且都很正确,可是给分的好象不多吧 See MSDN\Technical Articles\Windows Platform\Base Services\Creating a SimpleWindows NT Service in C++and u get his samples! To CoolHg: 干吗要用图形界面的Service?你可以作一个控制程序连接上服务嘛,然后再控制程序中控制服务,SQLServer,ORACLE不就是这样的吗?至于图形界面的服务,我也不会。To kirk: NT 服务依赖就是你的服务必须在你所依赖的服务已经起来的情况下才能起来。在CreateService函数的参数中有一个就是:SC_HANDLE CreateService( SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPCTSTR lpDisplayName, DWORD dwDesiredAccess, DWORD dwServiceType, DWORD dwStartType, DWORD dwErrorControl, LPCTSTR lpBinaryPathName, LPCTSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCTSTR lpDependencies, //填入你的服务依赖的服务的名称 LPCTSTR lpServiceStartName, LPCTSTR lpPassword); FireAngel我有一个数据库定期备份程序要写,已经写好了,只可惜是Win32应用程序,想把它改写为Service程序,这样就不用登录到服务器了,本来老板也没这么要求,不过我想顺便自己也能学一点东西,所以就这么看了一下相关方面的文档,只是没有关于用户界面的文档,把这个程序重写一遍我是不想了,关于写控制Service的程序到也写了一个那就这样吧,就算我写了出来也不会有什么好处的,毕竟这个公司只用一些PB或Java,成天与Table和Fileds打交道,对于我这方面是从不看重的 谢谢大家的帮助!我把这个帖子又增加了一些分数。FireAngel给了我很大的帮助,给40分;另为2位朋友的回答对我也有启发,各给10分纪念! 如何截获消息,不让它继续默认操作 CDialog::PreTranslateMessage里怎样知道触发WM_KEYDOWN消息时是否同时按下了CTRL键? 自己加了个最大化按钮,问:如何给这个最大化按钮添家事件进行最大化响应? 组合框的问题 为什么查询前必须插入 新手问题。。。。函数自动提示出不来。 为什么? 菜单问题 这是什么错误啊? 说两句 寻找正在学习Socket API网络编程的网友,共同进步. 我要做一个双向链表,请问如何做好?
---- Windows NT Server 提 供 多 种 功 能 强 大 的 服 务(Service), 例 如FTP,WWW 或 远 程 登 录 服 务, 另 外 常 用 的 数 据 库 服 务 器 也 是 以Service 的 形 式 存 在 于NT Server 上 的, 如Sybase SQL Server For NT。Service 一 般 在NT 启 动 时 自 动 启 动, 在NT 关 机 时 停 止。 但 是 有 时 用 户 可 能 想 手 工 启 动﹑ 暂 停﹑ 停 止 某 项Service, 这 就 需 要 在 控 制 面 板 中 进 行 配 置, 对 于 不 太 熟 悉NT 的 用 户 来 说 比 较 困 难; 对 于 软 件 开 发 人 员, 有 时 需 要 在 软 件 中 访 问 和 操 作 某 项Service, 甚 至 可 能 需 要 开 发 新Service 的 提 供 给 用 户 使 用。 上 面 两 种 情 况 都 可 以 通 过 对Service 的 编 程 来 解 决。 对Service 的 编 程 涉 及 到NT 的 内 核, 比 较 复 杂 且 相 关 资 料 较 少, 给 软 件 开 发 人 员 带 来 很 多 困 难, 笔 者 通 过 对Windows NT 的API 的 分 析 找 到 了 相 应 的 编 程 方 法, 再 此 介 绍 给 大 家。
---- 在Windows NT 下, 各 种Service 都 存 在service control manager database 中, 因 此 我 们 可 以 通 过 对service control manager database 进 行 操 作 来 实 现 对Service 的 编 程。 下 面 介 绍 常 用 的 函 数:
1:SC_HANDLE OpenSCManager
(LPCTSTR lpszMachineName,
LPCTSTR lpszDatabaseName,
DWORD fdwDesiredAccess);
---- OpenSCManager 函 数 打 开 指 定 计 算 机 上 的service control manager database 。 其 中 参 数lpszMachineName 指 定 计 算 机 名, 若 为 空 则 指 定 为 本 机。 参 数lpszDatabaseName 指 定 要 打 开 的service control manager database, 默 认 为 空。
---- 参 数fdwDesiredAccess 指 定 操 作 的 权 限, 可 以 为 下 面 取 值 之 一
SC_MANAGER_ALL_ACCESS //所有权限
SC_MANAGER_CONNECT
//允许连接service control manager
SC_MANAGER_CREATE_SERVICE
//允许创建服务对象并把它加入
service control manager database
SC_MANAGER_ENUMERATE_SERVICE
//允许枚举service control manager database中的服务
SC_MANAGER_LOCK
//允许锁住service control manager database
SC_MANAGER_QUERY_LOCK_STATUS
//允许获取service control manager database的封锁信息
---- 函 数 返 回 值: 函 数 执 行 成 功 则 返 回 一 个 指 向service control manager database 的 句 柄, 失 败 则 返 回NULL。
2:SC_HANDLE OpenService
(SC_HANDLE schSCManager,
LPCTSTR lpszServiceName,
DWORD fdwDesiredAccess);
---- OpenService 函 数 打 开 指 定 的Service。
---- 其 中 参 数schSCManager 是 指 向service control manager database 的 句 柄, 由OpenSCManager 函 数 返 回。
---- 参 数lpszServiceName 要 打 开 的 服 务 的 名 字, 注 意 大 小 写。
---- 参 数fdwDesiredAccess 指 定 操 作 的 权 限, 可 以 为 下 面 取 值 之 一
SERVICE_ALL_ACCESS
//所有权限
SERVICE_CHANGE_CONFIG
//允许更改服务的配置
SERVICE_ENUMERATE_DEPENDENTS
//允许获取依赖于该服务的其他服务
SERVICE_INTERROGATE
//允许立即获取服务状态
SERVICE_PAUSE_CONTINUE
//允许暂停和唤醒服务
SERVICE_QUERY_CONFIG
//允许获取服务配置
SERVICE_QUERY_STATU
//允许通过访问service control manager获取服务状态
SERVICE_START
//允许启动服务
SERVICE_STOP
//允许停止服务
SERVICE_USER_DEFINE_CONTROL
//允许用户指定特殊的服务控制码---- 函 数 返 回 值: 函 数 执 行 成 功 则 返 回 指 向 某 项 服 务 的 句 柄, 失 败 则 返 回NULL。
3:BOOL QueryServiceStatus
(SC_HANDLE schService,
LPSERVICE_STATUS lpssServiceStatus);
---- QueryServiceStatus函数返回指定服务的当前状态。
---- 其中参数schService是指向某项服务的句柄,由OpenService函数返回,且必须SERVICE_QUERY_STATUS的权限。
---- 参数lpssServiceStatus中存放返回的服务状态信息,结构如下
typedef struct _SERVICE_STATUS {
DWORD dwServiceType;
//服务类型
DWORD dwCurrentState;
//当前状态
DWORD dwControlsAccepted;
//服务可接受的控制码
DWORD dwWin32ExitCode;
//Win32出错代码
DWORD dwServiceSpecificExitCode;
//服务出错代码
DWORD dwCheckPoint;
//用于跟踪服务长时间操作
DWORD dwWaitHint;
//服务某一操作的最大允许时间,以毫秒为单位
} SERVICE_STATUS, *LPSERVICE_STATUS;
---- 函 数 返 回 值: 函 数 执 行 成 功 则 返 回True, 失 败 则 返 回False。
4:BOOL StartService(SC_HANDLE schService,
DWORD dwNumServiceArgs,
LPCTSTR *lpszServiceArgs);
---- StartService 函 数 启 动 指 定 的 服 务。
---- 其 中 参 数schService 是 指 向 某 项 服 务 的 句 柄, 由OpenService 函 数 返 回, 且 必 须 有SERVICE_START 的 权 限。
---- dwNumServiceArgs 为 启 动 服 务 所 需 的 参 数 的 个 数。
---- lpszServiceArgs 为 启 动 服 务 所 需 的 参 数。 函 数 返 回 值: 函 数 执 行 成 功 则 返 回True, 失 败 则 返 回False。
5:BOOL ControlService(
SC_HANDLE hService,
DWORD dwControl,
LPSERVICE_STATUS lpServiceStatus);
---- ControlService 函 数 向Win32 service 发 送 控 制 码。
---- 其 中 参 数hService 是 指 向 某 项 服 务 的 句 柄, 由OpenService 函 数 返 回。
---- 参 数dwControl 为 控 制 码, 常 用 的 有
SERVICE_CONTROL_STOP
//停止服务
SERVICE_CONTROL_PAUSE
//暂停服务
SERVICE_CONTROL_CONTINUE
//唤醒暂停的服务
SERVICE_CONTROL_INTERROGATE
//刷新某服务的状态
---- 参 数lpServiceStatus 指 向SERVICE_STATUS 结 构, 用 于 存 放 该 服 务 最 新 的 状 态 信 息。
---- 函 数 返 回 值: 函 数 执 行 成 功 则 返 回True, 失 败 则 返 回False。
6:BOOL EnumServicesStatus
(SC_HANDLE hSCManager,
DWORD dwServiceType,
DWORD dwServiceState,
LPENUM_SERVICE_STATUS lpServices,
DWORD cbBufSize,
LPDWORD pcbBytesNeeded,
LPDWORD lpServicesReturned,
LPDWORD lpResumeHandle);
---- EnumServicesStatus 函 数 用 于 枚 举NT 下 存 在 的Service。
---- 其 中 参 数hSCManager 是 指 向service control manager database 的 句 柄, 由OpenSCManager 函 数 返 回, 且 必 须 有SC_MANAGER_ENUMERATE_SERVICE 的 权 限。
---- 参 数dwServiceType 指 定 按 服 务 的 类 型 枚 举。
---- 参 数dwServiceState 指 定 按 服 务 的 状 态 枚 举。
---- 参 数lpServices 指 向ENUM_SERVICE_STATUS 结 构, 用 于 存 放 返 回 的 服 务 的 名 字 和 状 态 信 息。
---- 参 数cbBufSize 返 回 参 数lpServices 的 长 度, 以 字 节 为 单 位。
---- 参 数pcbBytesNeeded 返 回 获 取 剩 余 的Service 所 需 字 节 的 个 数。
---- 参 数lpServicesReturned 返 回 服 务 的 个 数。
---- 参 数lpResumeHandle, 当 第 一 次 调 用 时 该 参 数 为0, 当 该 函 数 再 次 被 调 用 以 获 取 另 外 的 信 息 时, 该 参 数 表 示 下 一 个 被 读 的Service。
---- 函 数 返 回 值: 函 数 执 行 成 功 则 返 回True, 失 败 则 返 回False。
---- 值 得 注 意 的 是 通 常 情 况 下 该 函 数 返 回 的 结 果 为FALSE, 我 们 可 以 调 用GetLastError() 来 获 取 进 一 步 信 息。 因 为 一 台 机 器 上 有 多 种 服 务 存 在, 所 以GetLastError() 应 为ERROR_MORE_DATA, 此 时 应 再 次 调 用EnumServicesStatus 函 数 以 获 取 正 确 的Service 列 表。
1.用vc->NEW->ATL Com APPWizard->Service不寫代碼即可生成一什麼都不干的NT Service
程序,
2.安裝;
NT下Run 你的應用程序 /SERVICE即可
在這外殼內再加入你的代碼
很簡單
《Windows 2000编程技术内幕》ISBN:7-111-07632-X/TP.1271
你好,随时可见你的踪影,我想问一下,如何编写有界面的Service程序,MSDN里好象没有这方面的例程,虽然文档中好象也讲过可以编写用户界面的Service
另外你这么辛苦好象有点不太值吧,我看你回答了不少问题,而且都很正确,可是给分的好象不多吧
Windows NT Service in C++
and u get his samples!
干吗要用图形界面的Service?你可以作一个控制程序连接上服务嘛,然后再控制程序中控制服务,SQLServer,ORACLE不就是这样的吗?至于图形界面的服务,我也不会。To kirk:
NT 服务依赖就是你的服务必须在你所依赖的服务已经起来的情况下才能起来。在CreateService函数的参数中有一个就是:
SC_HANDLE CreateService(
SC_HANDLE hSCManager,
LPCTSTR lpServiceName,
LPCTSTR lpDisplayName,
DWORD dwDesiredAccess,
DWORD dwServiceType,
DWORD dwStartType,
DWORD dwErrorControl,
LPCTSTR lpBinaryPathName,
LPCTSTR lpLoadOrderGroup,
LPDWORD lpdwTagId,
LPCTSTR lpDependencies, //填入你的服务依赖的服务的名称
LPCTSTR lpServiceStartName,
LPCTSTR lpPassword
);
我有一个数据库定期备份程序要写,已经写好了,只可惜是Win32应用程序,想把它改写为Service程序,这样就不用登录到服务器了,本来老板也没这么要求,不过我想顺便自己也能学一点东西,所以就这么看了一下相关方面的文档,只是没有关于用户界面的文档,把这个程序重写一遍我是不想了,
关于写控制Service的程序到也写了一个
那就这样吧,就算我写了出来也不会有什么好处的,毕竟这个公司只用一些PB或Java,成天与Table和Fileds打交道,对于我这方面是从不看重的
FireAngel给了我很大的帮助,给40分;另为2位朋友的回答对我也有启发,各给10分纪念!