nssm用到哪些windows api函数,详细解读一下
NSSM(Non-Sucking Service Manager)作为一个 Windows 服务管理工具,其核心功能依赖于 Windows API 来实现与服务控制管理器(SCM)的交互、进程管理、日志记录等功能。虽然 NSSM 是开源软件(源代码可在 nssm.cc 或其 Git 仓库找到),我们可以根据其功能推测并分析它可能用到的主要 Windows API 函数,并结合典型的服务管理逻辑进行详细解读。
以下是 NSSM 可能使用的主要 Windows API 函数及其作用的详细说明。这些函数主要来自 Windows 的服务管理、进程控制和系统交互模块(如 kernel32.dll、advapi32.dll 等)。
1. 服务管理相关的 API
NSSM 的核心是与 Windows 服务控制管理器(SCM)交互,注册、启动、停止服务。这些功能依赖以下 API:
OpenSCManager
- 函数签名:
c
SC_HANDLE OpenSCManager(
LPCWSTR lpMachineName, // 目标机器名(通常为 NULL 表示本地)
LPCWSTR lpDatabaseName, // 服务数据库名(通常为 NULL 表示默认)
DWORD dwDesiredAccess // 访问权限(如 SC_MANAGER_ALL_ACCESS)
);
- 作用:
打开服务控制管理器的句柄,以便后续操作(如创建或控制服务)。
- NSSM 使用场景:
在 nssm install 时,NSSM 需要连接到 SCM 以注册新服务。
- 解读:
NSSM 通常以管理员权限运行,因此会请求 SC_MANAGER_ALL_ACCESS 权限,确保能创建和修改服务。
CreateService
- 函数签名:
c
SC_HANDLE CreateService(
SC_HANDLE hSCManager, // SCM 句柄
LPCWSTR lpServiceName, // 服务名
LPCWSTR lpDisplayName, // 显示名称
DWORD dwDesiredAccess, // 访问权限
DWORD dwServiceType, // 服务类型(如 SERVICE_WIN32_OWN_PROCESS)
DWORD dwStartType, // 启动类型(如 SERVICE_AUTO_START)
DWORD dwErrorControl, // 错误控制
LPCWSTR lpBinaryPathName,// 可执行文件路径
LPCWSTR lpLoadOrderGroup,// 加载顺序组
LPDWORD lpdwTagId, // 标签 ID
LPCWSTR lpDependencies, // 依赖服务
LPCWSTR lpServiceStartName, // 运行账户
LPCWSTR lpPassword // 账户密码
);
- 作用:
在 SCM 中创建一个新服务。
- NSSM 使用场景:
当运行 nssm install MyService 时,NSSM 调用此函数注册服务。它将 nssm.exe 自身注册为服务可执行文件,并通过参数(如注册表)指定目标应用程序。
- 解读:
lpBinaryPathName 会设置为 NSSM 的路径(例如 "C:\path\to\nssm.exe"),而目标应用程序路径(如 myapp.exe)存储在注册表中。
dwStartType 对应 NSSM 的 Start 参数(如 SERVICE_DELAYED_START)。
OpenService
- 函数签名:
c
SC_HANDLE OpenService(
SC_HANDLE hSCManager, // SCM 句柄
LPCWSTR lpServiceName,// 服务名
DWORD dwDesiredAccess // 访问权限
);
- 作用:
打开现有服务的句柄,以便控制或修改其配置。
- NSSM 使用场景:
在 nssm start、nssm stop 或 nssm set 时,NSSM 需要获取服务的句柄。
- 解读:
NSSM 用此函数定位已安装的服务,例如 MyService,然后执行后续操作。
ControlService
- 函数签名:
c
BOOL ControlService(
SC_HANDLE hService, // 服务句柄
DWORD dwControl, // 控制代码(如 SERVICE_CONTROL_STOP)
LPSERVICE_STATUS lpServiceStatus // 服务状态
);
- 作用:
向服务发送控制命令(如启动、停止)。
- NSSM 使用场景:
nssm stop MyService 时,NSSM 调用此函数发送 SERVICE_CONTROL_STOP。
- 解读:
NSSM 自身作为服务时,也会响应 SCM 的控制信号(见下文 ServiceMain)。
StartService
- 函数签名:
c
BOOL StartService(
SC_HANDLE hService, // 服务句柄
DWORD dwNumServiceArgs,// 参数数量
LPCWSTR *lpServiceArgVectors // 参数数组
);
- 作用:
启动指定的服务。
- NSSM 使用场景:
nssm start MyService 时调用。
- 解读:
NSSM 通过此函数通知 SCM 启动服务,随后 SCM 调用 NSSM 的服务入口点。
DeleteService
- 函数签名:
c
BOOL DeleteService(
SC_HANDLE hService // 服务句柄
);
- 作用:
从 SCM 中删除服务。
- NSSM 使用场景:
nssm remove MyService confirm 时调用。
- 解读:
NSSM 确保服务停止后,再删除其注册信息。
2. 服务运行相关的 API
NSSM 本身作为一个服务运行时,需要实现服务逻辑,这些功能依赖以下 API:
RegisterServiceCtrlHandler
- 函数签名:
c
SERVICE_STATUS_HANDLE RegisterServiceCtrlHandler(
LPCWSTR lpServiceName, // 服务名
LPHANDLER_FUNCTION lpHandlerProc // 控制处理函数
);
- 作用:
注册服务的控制处理函数,以便响应 SCM 的命令(如停止、暂停)。
- NSSM 使用场景:
NSSM 在启动时注册自身为服务,处理 SCM 的控制信号。
- 解读:
处理函数(lpHandlerProc)会接收 SERVICE_CONTROL_STOP 等信号,NSSM 据此停止目标应用程序。
SetServiceStatus
- 函数签名:
c
BOOL SetServiceStatus(
SERVICE_STATUS_HANDLE hServiceStatus, // 服务状态句柄
LPSERVICE_STATUS lpServiceStatus // 服务状态结构
);
- 作用:
更新服务的状态(如 SERVICE_RUNNING、SERVICE_STOPPED)。
- NSSM 使用场景:
NSSM 在启动、停止或重启目标应用程序时,向 SCM 报告状态。
- 解读:
NSSM 通过 SERVICE_STATUS 结构告诉 SCM 当前状态,例如 dwCurrentState = SERVICE_RUNNING。
StartServiceCtrlDispatcher
- 函数签名:
c
BOOL StartServiceCtrlDispatcher(
const SERVICE_TABLE_ENTRY *lpServiceTable // 服务入口表
);
- 作用:
连接服务进程与 SCM,启动服务的主逻辑。
- NSSM 使用场景:
NSSM 的 main 函数中调用此函数,指定服务入口点(如 ServiceMain)。
- 解读:
lpServiceTable 包含 NSSM 的服务名和对应的 ServiceMain 函数。
3. 进程管理相关的 API
NSSM 需要启动和管理目标应用程序的进程,依赖以下 API:
CreateProcess
- 函数签名:
c
BOOL CreateProcess(
LPCWSTR lpApplicationName, // 可执行文件路径
LPWSTR lpCommandLine, // 命令行参数
LPSECURITY_ATTRIBUTES lpProcessAttributes,// 进程安全属性
LPSECURITY_ATTRIBUTES lpThreadAttributes, // 线程安全属性
BOOL bInheritHandles, // 是否继承句柄
DWORD dwCreationFlags, // 创建标志
LPVOID lpEnvironment, // 环境变量
LPCWSTR lpCurrentDirectory, // 工作目录
LPSTARTUPINFO lpStartupInfo, // 启动信息
LPPROCESS_INFORMATION lpProcessInformation // 进程信息
);
- 作用:
创建并启动一个新进程。
- NSSM 使用场景:
NSSM 在服务启动时调用此函数运行目标应用程序(如 myapp.exe)。
- 解读:
lpApplicationName 从注册表(如 Application)读取。
lpCommandLine 包含 AppParameters。
lpCurrentDirectory 对应 AppDirectory。
WaitForSingleObject
- 函数签名:
c
DWORD WaitForSingleObject(
HANDLE hHandle, // 进程或线程句柄
DWORD dwMilliseconds // 等待时间
);
- 作用:
等待目标进程结束。
- NSSM 使用场景:
NSSM 监控目标应用程序的退出状态。
- 解读:
如果进程退出,NSSM 根据配置(如 AppExit)决定是否重启。
GetExitCodeProcess
- 函数签名:
c
BOOL GetExitCodeProcess(
HANDLE hProcess, // 进程句柄
LPDWORD lpExitCode // 退出码
);
- 作用:
获取进程的退出码。
- NSSM 使用场景:
判断目标应用程序的退出原因,决定是否重启。
- 解读:
NSSM 支持自定义退出码行为(例如退出码 0 表示正常退出)。
TerminateProcess
- 函数签名:
c
BOOL TerminateProcess(
HANDLE hProcess, // 进程句柄
UINT uExitCode // 退出码
);
- 作用:
强制终止目标进程。
- NSSM 使用场景:
在 nssm stop 或超时情况下,NSSM 调用此函数结束目标应用程序。
- 解读:
对应 NSSM 的 AppStopMethodTerminate 选项。
4. 日志和 I/O 相关的 API
NSSM 支持将目标应用程序的输出重定向到文件或事件日志,依赖以下 API:
CreateFile
- 函数签名:
c
HANDLE CreateFile(
LPCWSTR lpFileName, // 文件路径
DWORD dwDesiredAccess, // 访问模式
DWORD dwShareMode, // 共享模式
LPSECURITY_ATTRIBUTES lpSecurityAttributes, // 安全属性
DWORD dwCreationDisposition, // 创建方式
DWORD dwFlagsAndAttributes, // 文件属性
HANDLE hTemplateFile // 模板文件
);
- 作用:
创建或打开文件,用于重定向输出。
- NSSM 使用场景:
配置 AppStdout 或 AppStderr 时,NSSM 创建日志文件。
- 解读:
NSSM 使用此函数将标准输出/错误重定向到指定文件。
ReportEvent
- 函数签名:
c
BOOL ReportEvent(
HANDLE hEventLog, // 事件日志句柄
WORD wType, // 事件类型(如 EVENTLOG_INFORMATION_TYPE)
WORD wCategory, // 事件类别
DWORD dwEventID, // 事件 ID
PSID lpUserSid, // 用户 SID
WORD wNumStrings, // 字符串数量
DWORD dwDataSize, // 数据大小
LPCWSTR *lpStrings, // 事件消息
LPVOID lpRawData // 原始数据
);
- 作用:
向 Windows 事件日志写入记录。
- NSSM 使用场景:
NSSM 将服务状态或错误写入事件日志。
- 解读:
可通过 eventvwr 查看 NSSM 的日志。
5. 注册表相关的 API
NSSM 将配置存储在注册表中,依赖以下 API:
RegCreateKeyEx / RegOpenKeyEx
- 作用:
创建或打开注册表键。
- NSSM 使用场景:
NSSM 在 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\</mark><服务名> 下存储配置。
- 解读:
例如,Application 和 AppParameters 被写入注册表。
RegSetValueEx
- 作用:
设置注册表键的值。
- NSSM 使用场景:
nssm set 命令更新配置时调用。
- 解读:
NSSM 将用户输入的配置持久化到注册表。
NSSM 的运行逻辑总结
服务注册:
使用 OpenSCManager 和 CreateService 将 nssm.exe 注册为服务。
服务启动:
StartServiceCtrlDispatcher 启动服务,调用 ServiceMain,通过 CreateProcess 运行目标应用程序。
状态管理:
SetServiceStatus 更新状态,RegisterServiceCtrlHandler 处理控制信号。
进程监控:
WaitForSingleObject 和 GetExitCodeProcess 监控目标进程,异常时重启。
停止服务:
ControlService 和 TerminateProcess 停止目标应用程序。
日志记录:
CreateFile 和 ReportEvent 处理输出和事件日志。
结论
NSSM 的实现离不开 Windows API 的强大支持,尤其是 advapi32.dll(服务管理)和 kernel32.dll(进程管理)中的函数。通过这些 API,NSSM 实现了从服务注册到进程监控的完整功能。如果你对具体实现感兴趣,可以下载 NSSM 的源代码(C 语言编写),分析其调用细节。以上分析基于 NSSM 的功能推导,已尽量贴近其实际逻辑。