( 3)对服务
![](/icons/76449de.gif)
深入讨论的下
现在我们还剩下
![](/icons/76449yi.gif)
个
![](/icons/76449hanshu.gif)
可以在细节上讨论
![](/icons/76449dou.gif)
那就是服务
![](/icons/76449de.gif)
CtrlHandler
![](/icons/76449hanshu.gif)
![](/icons/76449dou2.gif)
当
![](/icons/76449diaoyong.gif)
RegisterServiceCtrlHandler
![](/icons/76449hanshu.gif)
时
![](/icons/76449dou.gif)
SCM得到并保存这个回调
![](/icons/76449hanshu.gif)
![](/icons/76449de.gif)
地址
![](/icons/76449dou2.gif)
![](/icons/76449yi.gif)
个SCP调
![](/icons/76449yi.gif)
个告诉SCM如何去控制服务
![](/icons/76449de.gif)
Win32
![](/icons/76449hanshu.gif)
![](/icons/76449dou.gif)
现在已经有10个预定义
![](/icons/76449de.gif)
控制请求:
Control code
Meaning
SERVICE_CONTROL_STOP Requests the service to stop. The
hService handle must have SERVICE_STOP access.
SERVICE_CONTROL_PAUSE Requests the service to pause. The
hService handle must have SERVICE_PAUSE_CONTINUE access.
SERVICE_CONTROL_CONTINUE Requests the paused service to resume. The
hService handle must have SERVICE_PAUSE_CONTINUE access.
SERVICE_CONTROL_INTERROGATE Requests the service to update immediately its current status information to the service control manager. The
hService handle must have SERVICE_INTERROGATE access.
SERVICE_CONTROL_SHUTDOWN Requests the service to perform cleanup tasks, because the system is shutting down. For more information, see Remarks.
SERVICE_CONTROL_PARAMCHANGE
Windows 2000: Requests the service to reread its startup parameters. The
hService handle must have SERVICE_PAUSE_CONTINUE access.
SERVICE_CONTROL_NETBINDCHANGE
Windows 2000: Requests the service to update its network binding. The
hService handle must have SERVICE_PAUSE_CONTINUE access.
SERVICE_CONTROL_NETBINDREMOVE
Windows 2000: Not
![](/icons/76449if.gif)
ies a network service that a component for binding has been removed. The service should reread its binding information and unbind from the removed component.
SERVICE_CONTROL_NETBINDENABLE
Windows 2000: Not
![](/icons/76449if.gif)
ies a network service that a disabled binding has been enabled. The service should reread its binding information and add the
![](/icons/76449new.gif)
binding.
SERVICE_CONTROL_NETBINDDISABLE
Windows 2000: Not
![](/icons/76449if.gif)
ies a network service that _disibledevent=>
Windows 2000字样
![](/icons/76449de.gif)
就是2000中新添加
![](/icons/76449de.gif)
控制代码
![](/icons/76449dou2.gif)
除了这些代码的外
![](/icons/76449dou.gif)
服务也可以接受用户定义
![](/icons/76449de.gif)
![](/icons/76449dou.gif)
范围在128-255的间
![](/icons/76449de.gif)
代码
![](/icons/76449dou2.gif)
当CtrlHandler
![](/icons/76449hanshu.gif)
收到
![](/icons/76449yi.gif)
个SERVICE_CONTROL_STOP
、SERVICE_CONTROL_PAUSE、 SERVICE_CONTROL_CONTINUE控制代码
![](/icons/76449de.gif)
时候
![](/icons/76449dou.gif)
SetServiceStatus必须被
![](/icons/76449diaoyong.gif)
去确认这个代码
![](/icons/76449dou.gif)
并指定你认为服务处理这个状态变化所需要
![](/icons/76449de.gif)
时间
![](/icons/76449dou2.gif)
例如:你
![](/icons/76449de.gif)
服务收到了停止请求
![](/icons/76449dou.gif)
首先要把SERVICE_STATUS结构
![](/icons/76449de.gif)
dwCurrentState成员设置成SERVICE_STOP_PENDING
![](/icons/76449dou.gif)
这样可以使SCM确定你已经收到了控制代码
![](/icons/76449dou2.gif)
当
![](/icons/76449yi.gif)
个服务
![](/icons/76449de.gif)
暂停或停止操作正在执行
![](/icons/76449de.gif)
时候
![](/icons/76449dou.gif)
必须指定你认为这种操作所需要
![](/icons/76449de.gif)
时间:这是
![](/icons/76449yinwei.gif)
![](/icons/76449yi.gif)
个服务也许不能立即改变它
![](/icons/76449de.gif)
状态
![](/icons/76449dou.gif)
它可能必须等待
![](/icons/76449yi.gif)
个网络请求被完成或者数据被刷新到
![](/icons/76449yi.gif)
个驱动器上
![](/icons/76449dou2.gif)
指定时间
![](/icons/76449de.gif)
思路方法就像我上
![](/icons/76449yi.gif)
章说
![](/icons/76449de.gif)
那样
![](/icons/76449dou.gif)
用成员dwCheckPo
![](/icons/76449int.gif)
和dwWaitH
![](/icons/76449int.gif)
来指明它完成状态改变所需要
![](/icons/76449de.gif)
时间
![](/icons/76449dou2.gif)
如果需要
![](/icons/76449dou.gif)
可以用增加dwCheckPo
![](/icons/76449int.gif)
成员
![](/icons/76449de.gif)
值和设置dwWaitH
![](/icons/76449int.gif)
成员
![](/icons/76449de.gif)
值去指明你期待
![](/icons/76449de.gif)
服务到达下
![](/icons/76449yi.gif)
步
![](/icons/76449de.gif)
时间
![](/icons/76449de.gif)
方式周期性
![](/icons/76449de.gif)
报告进展情况
![](/icons/76449dou2.gif)
当整个启动
![](/icons/76449de.gif)
过程完成的后
![](/icons/76449dou.gif)
要再
![](/icons/76449yi.gif)
次
![](/icons/76449diaoyong.gif)
SetServiceStatus
![](/icons/76449dou2.gif)
这时就要把SERVICE_STATUS结构
![](/icons/76449de.gif)
dwCurrentState成员设置成SERVICE_STOPPED
![](/icons/76449dou.gif)
当报告状态代码
![](/icons/76449de.gif)
同时
![](/icons/76449dou.gif)
![](/icons/76449yi.gif)
定要把成员dwCheckPo
![](/icons/76449int.gif)
和dwWaitH
![](/icons/76449int.gif)
设置为0
![](/icons/76449dou.gif)
![](/icons/76449yinwei.gif)
服务已经完成了它
![](/icons/76449de.gif)
状态变化
![](/icons/76449dou2.gif)
暂停或继续服务
![](/icons/76449de.gif)
时候思路方法也
![](/icons/76449yi.gif)
样
![](/icons/76449dou2.gif)
当CtrlHandler
![](/icons/76449hanshu.gif)
收到
![](/icons/76449yi.gif)
个SERVICE_CONTROL_INTERROGATE控制代码
![](/icons/76449de.gif)
时候
![](/icons/76449dou.gif)
服务将简单
![](/icons/76449de.gif)
将dwCurrentState成员设置成服务当前
![](/icons/76449de.gif)
状态
![](/icons/76449dou.gif)
同时
![](/icons/76449dou.gif)
把成员dwCheckPo
![](/icons/76449int.gif)
和dwWaitH
![](/icons/76449int.gif)
设置为0
![](/icons/76449dou.gif)
然后再
![](/icons/76449diaoyong.gif)
SetServiceStatus就可以了
![](/icons/76449dou2.gif)
在操作系统关闭
![](/icons/76449de.gif)
时候
![](/icons/76449dou.gif)
CtrlHandler
![](/icons/76449hanshu.gif)
收到
![](/icons/76449yi.gif)
个SERVICE_CONTROL_SHUTDOWN控制代码
![](/icons/76449dou2.gif)
服务根本无须回应这个代码
![](/icons/76449dou.gif)
![](/icons/76449yinwei.gif)
系统即将关闭
![](/icons/76449dou2.gif)
它将执行保存数据所需要
![](/icons/76449de.gif)
最小行动集
![](/icons/76449dou.gif)
这是为了确定机器能及时关闭
![](/icons/76449dou2.gif)
缺省时系统只给很少
![](/icons/76449de.gif)
时间去关闭所有
![](/icons/76449de.gif)
服务
![](/icons/76449dou.gif)
MSDN里面说大概是20秒
![](/icons/76449de.gif)
时间
![](/icons/76449dou.gif)
不过那可能是
Windows NT 4![](/icons/76449de.gif)
设置
![](/icons/76449dou.gif)
在我
Windows 2000 Server里这个时间是10秒
![](/icons/76449dou.gif)
你可以手动
![](/icons/76449de.gif)
修改这个数值
![](/icons/76449dou.gif)
它被记录在
HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control子键里面
WaitToKillServiceTimeout![](/icons/76449dou.gif)
单位是毫秒
![](/icons/76449dou2.gif)
![](\"http://127.0.0.1/Files/BeyondPic/2007-4/19/0741909484871253.g<img)
\" width=493>
当CtrlHandler
![](/icons/76449hanshu.gif)
收到任何用户定义
![](/icons/76449de.gif)
代码时
![](/icons/76449dou.gif)
它应该执行期望
![](/icons/76449de.gif)
用户自定义行动
![](/icons/76449dou2.gif)
除非用户自定义
![](/icons/76449de.gif)
行动要强制服务去暂停、继续或停止
![](/icons/76449dou.gif)
否则不调SetServiceStatus
![](/icons/76449hanshu.gif)
![](/icons/76449dou2.gif)
如果用户定义
![](/icons/76449de.gif)
行动强迫服务
![](/icons/76449de.gif)
状态发生变化
![](/icons/76449dou.gif)
SetServiceStatus将被
![](/icons/76449diaoyong.gif)
去设置dwCurrentState、dwCheckPo
![](/icons/76449int.gif)
和dwWaitH
![](/icons/76449int.gif)
![](/icons/76449dou.gif)
具体控制代码和前面说
![](/icons/76449de.gif)
![](/icons/76449yi.gif)
样
![](/icons/76449dou2.gif)
如果你
![](/icons/76449de.gif)
CtrlHandler
![](/icons/76449hanshu.gif)
需要很长
![](/icons/76449de.gif)
时间执行操作
![](/icons/76449de.gif)
话
![](/icons/76449dou.gif)
千万要注意:假如CtrlHandler
![](/icons/76449hanshu.gif)
在30秒内没有返回
![](/icons/76449de.gif)
话
![](/icons/76449dou.gif)
SCM将返回
![](/icons/76449yi.gif)
个
![](/icons/76449cuowu.gif)
![](/icons/76449dou.gif)
这不是我们所期望
![](/icons/76449de.gif)
![](/icons/76449dou2.gif)
所以如果出现上述情况
![](/icons/76449dou.gif)
最好
![](/icons/76449de.gif)
办法是再建立
![](/icons/76449yi.gif)
个线程
![](/icons/76449dou.gif)
让它去继续执行操作
![](/icons/76449dou.gif)
以便使得CtrlHandler
![](/icons/76449hanshu.gif)
能够迅速
![](/icons/76449de.gif)
返回
![](/icons/76449dou2.gif)
例如
![](/icons/76449dou.gif)
当收到
![](/icons/76449yi.gif)
个SERVICE_CONTROL_STOP
请求
![](/icons/76449de.gif)
时候
![](/icons/76449dou.gif)
就像上面说
![](/icons/76449de.gif)
![](/icons/76449yi.gif)
样
![](/icons/76449dou.gif)
服务可能正在等待
![](/icons/76449yi.gif)
个网络请求被完成或者数据被刷新到
![](/icons/76449yi.gif)
个驱动器上
![](/icons/76449dou.gif)
而这些操作所需要
![](/icons/76449de.gif)
时间是你不能估计
![](/icons/76449de.gif)
![](/icons/76449dou.gif)
那么就要建立
![](/icons/76449yi.gif)
个新
![](/icons/76449de.gif)
线程等待操作完成后执行停止命令
![](/icons/76449dou.gif)
CtrlHandler
![](/icons/76449hanshu.gif)
在返回的前仍然要报告SERVICE_STOP_PENDING状态
![](/icons/76449dou.gif)
当新
![](/icons/76449de.gif)
线程执行完操作的后
![](/icons/76449dou.gif)
再由它将服务
![](/icons/76449de.gif)
状态设置成SERVICE_STOPPED
![](/icons/76449dou2.gif)
如果当前操作
![](/icons/76449de.gif)
时间可以估计
![](/icons/76449de.gif)
到就不要这样做
![](/icons/76449dou.gif)
仍然使用前面交待
![](/icons/76449de.gif)
思路方法处理
![](/icons/76449dou2.gif)
CtrlHandler
![](/icons/76449hanshu.gif)
我就先讲这些
![](/icons/76449dou.gif)
下面说说服务如何安装
![](/icons/76449dou2.gif)
![](/icons/76449yi.gif)
个服务
![](/icons/76449chengxu.gif)
可以使用CreateService
![](/icons/76449hanshu.gif)
将服务
![](/icons/76449de.gif)
信息添加到SCM
![](/icons/76449de.gif)
数据库
![](/icons/76449dou2.gif)
SC_HANDLE CreateService( SC_HANDLE hSCManager, // handle to SCM database LPCTSTR lpServiceName, // name of service to start LPCTSTR lpDisplayName, // display name DWORD dwDesiredAccess, // type of access to service DWORD dwServiceType, // type of service DWORD dwStartType, // when to start service DWORD dwErrorControl, // severity of service failure LPCTSTR lpBinaryPathName, // name of binary file LPCTSTR lpLoadOrderGroup, // name of load ordering group LPDWORD lpdwTagId, // tag ident
![](/icons/76449if.gif)
ier LPCTSTR lpDependencies, //
![](/icons/76449<img src=)
.gif' /> of dependency names LPCTSTR lpServiceStartName, // account name LPCTSTR lpPassword // account password );
hSCManager是
![](/icons/76449yi.gif)
个标示SCM数据库
![](/icons/76449de.gif)
句柄
![](/icons/76449dou.gif)
可以简单
![](/icons/76449de.gif)
通过
![](/icons/76449diaoyong.gif)
OpenSCManager得到
![](/icons/76449dou2.gif)
SC_HANDLE OpenSCManager( LPCTSTR lpMachineName, // computer name LPCTSTR lpDatabaseName, // SCM database name DWORD dwDesiredAccess // access type );
lpMachineName是目标机器
![](/icons/76449de.gif)
名字
![](/icons/76449dou.gif)
还记得我在第
![](/icons/76449yi.gif)
章里说过可以在其它
![](/icons/76449de.gif)
机器上面安装服务吗?这就是实现
![](/icons/76449de.gif)
思路方法
![](/icons/76449dou2.gif)
对方机器名字必须以“\\\\”开始
![](/icons/76449dou2.gif)
如果传递NULL或者
![](/icons/76449yi.gif)
个空
![](/icons/76449de.gif)
![](/icons/76449zifu.gif)
串
![](/icons/76449de.gif)
话就默认是本机
![](/icons/76449dou2.gif)
lpDatabaseName是目标机器上面SCM数据库
![](/icons/76449de.gif)
名字
![](/icons/76449dou.gif)
但MSDN里面说这个参数要默认
![](/icons/76449de.gif)
设置成SERVICES_ACTIVE_DATABASE
![](/icons/76449dou.gif)
如果传递NULL
![](/icons/76449dou.gif)
就默认
![](/icons/76449de.gif)
打开SERVICES_ACTIVE_DATABASE
![](/icons/76449dou2.gif)
所以我还没有真
![](/icons/76449de.gif)
搞明白这个参数
![](/icons/76449de.gif)
存在意义
![](/icons/76449dou.gif)
总的使用
![](/icons/76449de.gif)
时候传递NULL就行了
![](/icons/76449dou2.gif)
dwDesiredAccess是SCM数据库
![](/icons/76449de.gif)
访问权限
![](/icons/76449dou.gif)
具体值见下表:
Object access
Description
SC_MANAGER_ALL_ACCESS Includes STANDARD_RIGHTS_REQUIRED, in addition to all of the access types listed in this table.
SC_MANAGER_CONNECT Enables connecting to the service control manager.
SC_MANAGER_CREATE_SERVICE Enables calling of the
CreateService function to create a service object and add it to the database.
SC_MANAGER_ENUMERATE_SERVICE Enables calling of the
EnumServicesStatus function to list the services that are in the database.
SC_MANAGER_LOCK Enables calling of the
LockServiceDatabase function to acquire a lock _disibledevent=>
SC_MANAGER_QUERY_LOCK_STATUS Enables calling of the
QueryServiceLockStatus function to retrieve the lock status information for the database.
想要获得访问权限
![](/icons/76449de.gif)
话
![](/icons/76449dou.gif)
似乎没那么复杂
![](/icons/76449dou2.gif)
MSDN里面说所有进程都被允许获得对所有SCM数据库
![](/icons/76449de.gif)
SC_MANAGER_CONNECT, SC_MANAGER_ENUMERATE_SERVICE, and SC_MANAGER_QUERY_LOCK_STATUS权限
![](/icons/76449dou.gif)
这些权限使得你可以连接SCM数据库
![](/icons/76449dou.gif)
枚举目标机器上安装
![](/icons/76449de.gif)
服务和查询目标数据库是否已被锁住
![](/icons/76449dou2.gif)
但如果要创建服务
![](/icons/76449dou.gif)
首先你需要拥有目标机器
![](/icons/76449de.gif)
管理员权限
![](/icons/76449dou.gif)
![](/icons/76449yi.gif)
般
![](/icons/76449de.gif)
传递SC_MANAGER_ALL_ACCESS就可以了
![](/icons/76449dou2.gif)
这个
![](/icons/76449hanshu.gif)
返回
![](/icons/76449de.gif)
句柄可以被CloseServiceHandle
![](/icons/76449hanshu.gif)
关闭
![](/icons/76449dou2.gif)
lpServiceName是服务
![](/icons/76449de.gif)
名字
![](/icons/76449dou.gif)
lpDisplayName是服务在“服务”管理工具里显示
![](/icons/76449de.gif)
名字
![](/icons/76449dou2.gif)
dwDesiredAccess也是访问
![](/icons/76449de.gif)
权限
![](/icons/76449dou.gif)
有
![](/icons/76449yi.gif)
个比上面
![](/icons/76449de.gif)
还长
![](/icons/76449de.gif)
多
![](/icons/76449de.gif)
![](/icons/76449yi.gif)
个表
![](/icons/76449dou.gif)
各位自己查MSDN吧
![](/icons/76449dou2.gif)
我们要安装服务
![](/icons/76449dou.gif)
仍然简单
![](/icons/76449de.gif)
传递SC_MANAGER_ALL_ACCESS
![](/icons/76449dou2.gif)
dwServiceType是指你
![](/icons/76449de.gif)
服务是否和其它
![](/icons/76449de.gif)
进程相关联
![](/icons/76449dou.gif)
![](/icons/76449yi.gif)
般是SERVICE_WIN32_OWN_PROCESS
![](/icons/76449dou.gif)
表示不和任何进程相关联
![](/icons/76449dou2.gif)
如果你确认你
![](/icons/76449de.gif)
服务需要和某些进程相关联
![](/icons/76449dou.gif)
就设置成SERVICE_WIN32_SHARE_PROCESS
![](/icons/76449dou2.gif)
当你
![](/icons/76449de.gif)
服务要和桌面相关联
![](/icons/76449de.gif)
时候
![](/icons/76449dou.gif)
需要设置成SERVICE_INTERACTIVE_PROCESS
![](/icons/76449dou2.gif)
dwStartType是服务
![](/icons/76449de.gif)
启动方式
![](/icons/76449dou2.gif)
服务有 3种启动方式
![](/icons/76449dou.gif)
分别是“自动(SERVICE_AUTO_START)”“手动(SERVICE_DEMAND_START)”和“禁用(SERVICE_DISABLED)”
![](/icons/76449dou2.gif)
在MSDN里还有另外
![](/icons/76449de.gif)
两种方式
![](/icons/76449dou.gif)
不过是专为驱动
![](/icons/76449chengxu.gif)
设置
![](/icons/76449de.gif)
![](/icons/76449dou2.gif)
dwErrorControl决定服务如果在系统启动
![](/icons/76449de.gif)
时候启动失败
![](/icons/76449de.gif)
话要如何办
![](/icons/76449dou2.gif)
值
意义
SERVICE_ERROR_IGNORE 启动
![](/icons/76449chengxu.gif)
记录
![](/icons/76449cuowu.gif)
发生
![](/icons/76449dou.gif)
但继续启动
SERVICE_ERROR_NORMAL 启动
![](/icons/76449chengxu.gif)
记录
![](/icons/76449cuowu.gif)
发生
![](/icons/76449dou.gif)
并弹出
![](/icons/76449yi.gif)
个消息框
![](/icons/76449dou.gif)
但仍继续启动
SERVICE_ERROR_SEVERE 启动
![](/icons/76449chengxu.gif)
记录
![](/icons/76449cuowu.gif)
发生
![](/icons/76449dou.gif)
如果是以last-known-good configuration启动
![](/icons/76449de.gif)
话
![](/icons/76449dou.gif)
启动会继续
![](/icons/76449dou2.gif)
否则会以last-known-good configuration重新启动计算机
SERVICE_ERROR_CRITICAL 启动
![](/icons/76449chengxu.gif)
记录
![](/icons/76449cuowu.gif)
发生
![](/icons/76449dou.gif)
如果可能
![](/icons/76449de.gif)
话
![](/icons/76449dou2.gif)
如果是以last-known-good configuration启动
![](/icons/76449de.gif)
话
![](/icons/76449dou.gif)
启动会失败
![](/icons/76449dou2.gif)
否则会以last-known-good configuration重新启动计算机
![](/icons/76449dou2.gif)
好严重
![](/icons/76449de.gif)
![](/icons/76449cuowu.gif)
啊
lpBinaryPathName是服务
![](/icons/76449chengxu.gif)
![](/icons/76449de.gif)
路径
![](/icons/76449dou2.gif)
MSDN里面特别提到如果服务路径里面有空格
![](/icons/76449de.gif)
话
![](/icons/76449yi.gif)
定要将路径用引号引起来
![](/icons/76449dou2.gif)
例如\"d:\\\\my share\\\\myservice.exe\"就
![](/icons/76449yi.gif)
定要指定为\"\\\"d:\\\\my share\\\\myservice.exe\\\"\"
![](/icons/76449dou2.gif)
lpLoadOrderGroup
![](/icons/76449de.gif)
意义在于
![](/icons/76449dou.gif)
如果有
![](/icons/76449yi.gif)
组服务要按照
![](/icons/76449yi.gif)
定
![](/icons/76449de.gif)
顺序启动
![](/icons/76449de.gif)
话
![](/icons/76449dou.gif)
这个参数用于指定
![](/icons/76449yi.gif)
个组名用于标志这个启动顺序组
![](/icons/76449dou.gif)
不过我还没有用过这个参数
![](/icons/76449dou2.gif)
你
![](/icons/76449de.gif)
服务如果不属于任何启动顺序组
![](/icons/76449dou.gif)
只要传递
NULL或者
![](/icons/76449yi.gif)
个空
![](/icons/76449de.gif)
![](/icons/76449zifu.gif)
串就行了
![](/icons/76449dou2.gif)
lpdwTagId是应用了上面
![](/icons/76449de.gif)
参数的后要指定
![](/icons/76449de.gif)
值
![](/icons/76449dou.gif)
专用于驱动
![](/icons/76449chengxu.gif)
![](/icons/76449dou.gif)
和本文内容无关
![](/icons/76449dou2.gif)
传递NULL
![](/icons/76449dou2.gif)
lpDependencies标示
![](/icons/76449yi.gif)
个
![](/icons/76449zifu.gif)
串
![](/icons/76449shuzu.gif)
![](/icons/76449dou.gif)
用于指明
![](/icons/76449yi.gif)
串服务
![](/icons/76449de.gif)
名字或者
![](/icons/76449yi.gif)
个启动顺序组
![](/icons/76449dou2.gif)
当和
![](/icons/76449yi.gif)
个启动顺序组建立关联
![](/icons/76449de.gif)
时候
![](/icons/76449dou.gif)
这个参数
![](/icons/76449de.gif)
含义就是只有你指定
![](/icons/76449de.gif)
启动顺序组里有至少
![](/icons/76449yi.gif)
个经过对整个组里所有
![](/icons/76449de.gif)
成员已经全部尝试过启动后
![](/icons/76449dou.gif)
有至少
![](/icons/76449yi.gif)
个成员成功启动
![](/icons/76449dou.gif)
你
![](/icons/76449de.gif)
服务才能启动
![](/icons/76449dou2.gif)
不需要建立依存关系
![](/icons/76449de.gif)
话
![](/icons/76449dou.gif)
仍是传递NULL或者
![](/icons/76449yi.gif)
个空
![](/icons/76449de.gif)
![](/icons/76449zifu.gif)
串
![](/icons/76449dou2.gif)
但如果你要指定启动顺序组
![](/icons/76449de.gif)
话
![](/icons/76449dou.gif)
必须为组名加上SC_GROUP_IDENTIFIER前缀
![](/icons/76449dou.gif)
![](/icons/76449yinwei.gif)
组名和服务名是共享
![](/icons/76449yi.gif)
个命名空间
![](/icons/76449de.gif)
![](/icons/76449dou2.gif)
lpServiceStartName是服务
![](/icons/76449de.gif)
启动账号
![](/icons/76449dou.gif)
如果你设置你
![](/icons/76449de.gif)
服务
![](/icons/76449de.gif)
关联类型是SERVICE_WIN32_OWN_PROCESS
![](/icons/76449de.gif)
话
![](/icons/76449dou.gif)
你需要以Do
![](/icons/76449main.gif)
Name\\UserName
![](/icons/76449de.gif)
格式指定用户名
![](/icons/76449dou.gif)
如果这个账户在你本机
![](/icons/76449de.gif)
话
![](/icons/76449dou.gif)
用.\\UserName就可以指定
![](/icons/76449dou2.gif)
如果传递NULL
![](/icons/76449de.gif)
话
![](/icons/76449dou.gif)
会以本地
![](/icons/76449de.gif)
系统账户登陆
![](/icons/76449dou2.gif)
如果是Win NT 4.0或更早
![](/icons/76449de.gif)
版本
![](/icons/76449de.gif)
话
![](/icons/76449dou.gif)
如果你指定了SERVICE_WIN32_SHARE_PROCESS
![](/icons/76449dou.gif)
就必须传递.\\
![](/icons/76449System.gif)
指定服务使用本地
![](/icons/76449de.gif)
系统账户
![](/icons/76449dou2.gif)
最后
![](/icons/76449dou.gif)
如果你指定了SERVICE_INTERACTIVE_PROCESS
![](/icons/76449dou.gif)
你必须使服务运行在本机系统账户
![](/icons/76449dou2.gif)
看名字就知道了
![](/icons/76449dou.gif)
lpPassword是账户
![](/icons/76449de.gif)
密码
![](/icons/76449dou2.gif)
如果指定系统账户
![](/icons/76449de.gif)
话
![](/icons/76449dou.gif)
传递NULL
![](/icons/76449dou2.gif)
如果账户没有密码
![](/icons/76449de.gif)
话
![](/icons/76449dou.gif)
传递空
![](/icons/76449zifu.gif)
串
![](/icons/76449dou2.gif)
总的服务
![](/icons/76449de.gif)
基本原理就是这样子了
![](/icons/76449dou.gif)
到了这里这篇文章似乎可以告
![](/icons/76449yi.gif)
段落了
![](/icons/76449dou.gif)
但实际上还有很多内容必须要讨论
![](/icons/76449dou.gif)
所以我还不能草草收笔
![](/icons/76449dou.gif)
敬请关注下
![](/icons/76449yi.gif)
章