8 个版本 (破坏性更新)
0.7.0 | 2024 年 4 月 16 日 |
---|---|
0.6.0 | 2023 年 3 月 7 日 |
0.5.0 | 2022 年 7 月 20 日 |
0.4.0 | 2021 年 8 月 12 日 |
0.1.0 | 2018 年 6 月 4 日 |
#12 在 Windows API 中
56,557 每月下载量
用于 24 个库 (20 个直接使用)
120KB
2K SLoC
windows-service
一个库,提供管理和实现 Windows 服务的功能。
实现 Windows 服务
本节描述了实现以 Windows 服务形式运行的程序的步骤,有关此类程序的完整源代码,请参阅示例文件夹。
基础
每个 Windows 服务都必须实现一个服务入口函数 fn(argc: u32, argv: *mut *mut u16)
并从应用程序的 main
中将其注册到系统中。
此库提供了一个方便的 define_windows_service!
宏,用于生成服务入口函数的低级别样板代码,该函数解析系统输入并将处理委托给用户定义的高级函数 fn(arguments: Vec<OsString>)
。
本指南将低级入口函数称为 ffi_service_main
,将高级函数称为 my_service_main
,但开发者如何调用它们取决于开发者。
#[macro_use]
extern crate windows_service;
use std::ffi::OsString;
use windows_service::service_dispatcher;
define_windows_service!(ffi_service_main, my_service_main);
fn my_service_main(arguments: Vec<OsString>) {
// The entry point where execution will start on a background thread after a call to
// `service_dispatcher::start` from `main`.
}
fn main() -> Result<(), windows_service::Error> {
// Register generated `ffi_service_main` with the system and start the service, blocking
// this thread until the service is stopped.
service_dispatcher::start("myservice", ffi_service_main)?;
Ok(())
}
处理服务事件
Windows 服务在其生命周期早期应该首先订阅服务事件,如停止或暂停等。
extern crate windows_service;
use std::ffi::OsString;
use windows_service::service::ServiceControl;
use windows_service::service_control_handler::{self, ServiceControlHandlerResult};
fn my_service_main(arguments: Vec<OsString>) {
if let Err(_e) = run_service(arguments) {
// Handle errors in some way.
}
}
fn run_service(arguments: Vec<OsString>) -> Result<(), windows_service::Error> {
let event_handler = move |control_event| -> ServiceControlHandlerResult {
match control_event {
ServiceControl::Stop => {
// Handle stop event and return control back to the system.
ServiceControlHandlerResult::NoError
}
// All services must accept Interrogate even if it's a no-op.
ServiceControl::Interrogate => ServiceControlHandlerResult::NoError,
_ => ServiceControlHandlerResult::NotImplemented,
}
};
// Register system service event handler
let status_handle = service_control_handler::register("myservice", event_handler)?;
Ok(())
}
请参阅相应的 MSDN 文章,了解事件处理器如何内部工作
https://msdn.microsoft.com/en-us/library/windows/desktop/ms685149(v=vs.85).aspx
更新服务状态
当系统启动实现Windows服务的应用程序时,它将自动进入 StartPending
状态。
应用程序需要完成初始化,获取 ServiceStatusHandle
(参见 service_control_handler::register
)并过渡到 Running
状态。
如果服务初始化耗时较长,应立即通过发送 StartPending
状态,使用 ServiceStatus::wait_hint
估算所需时间,并在服务完成初始化步骤时增加 ServiceStatus::checkpoint
。
在建议的 ServiceStatus::wait_hint
过期之前,系统将尝试杀死无法过渡到 Running
状态的服务。
在过渡到其他挂起状态及其对应目标状态时,也适用相同的概念。
请注意,可以安全地克隆 ServiceStatusHandle
并在任意线程中使用它。
extern crate windows_service;
use std::ffi::OsString;
use std::time::Duration;
use windows_service::service::{
ServiceControl, ServiceControlAccept, ServiceExitCode, ServiceState, ServiceStatus,
ServiceType,
};
use windows_service::service_control_handler::{self, ServiceControlHandlerResult};
fn my_service_main(arguments: Vec<OsString>) {
if let Err(_e) = run_service(arguments) {
// Handle error in some way.
}
}
fn run_service(arguments: Vec<OsString>) -> windows_service::Result<()> {
let event_handler = move |control_event| -> ServiceControlHandlerResult {
match control_event {
ServiceControl::Stop | ServiceControl::Interrogate => {
ServiceControlHandlerResult::NoError
}
_ => ServiceControlHandlerResult::NotImplemented,
}
};
// Register system service event handler
let status_handle = service_control_handler::register("my_service_name", event_handler)?;
let next_status = ServiceStatus {
// Should match the one from system service registry
service_type: ServiceType::OWN_PROCESS,
// The new state
current_state: ServiceState::Running,
// Accept stop events when running
controls_accepted: ServiceControlAccept::STOP,
// Used to report an error when starting or stopping only, otherwise must be zero
exit_code: ServiceExitCode::Win32(0),
// Only used for pending states, otherwise must be zero
checkpoint: 0,
// Only used for pending states, otherwise must be zero
wait_hint: Duration::default(),
};
// Tell the system that the service is running now
status_handle.set_service_status(next_status)?;
// Do some work
Ok(())
}
有关更多信息,请参阅MSDN上的“服务状态转换”文章
https://msdn.microsoft.com/en-us/library/windows/desktop/ee126211(v=vs.85).aspx
许可:MIT/Apache-2.0
依赖关系
~0–8.5MB
~58K SLoC