如果你需要在Windows下运行你的Rust应用,并希望你的应用以服务形式运行,那么这篇文章可能帮助到你。
windows-service-rs是一个为管理和实现Windows服务提供便利的库。
本节描述了实现作为Windows服务运行的程序的步骤,要了解此类程序的完整源代码,请查看examples文件夹。
每个Windows服务都必须实现一个服务入口函数fn(argc:u32,argv:*mut *mut u16),并从应用程序的main向系统注册。
这个库提供了一个方便的宏[define_windows_service!]来为服务输入函数生成一个低级别样板,该函数解析来自系统的输入并将处理委托给用户定义的更高级别函数fn(arguments:Vec<OsString>)。这是一个指南,关于低级别的入口函数ffi_service_main,和高级别的函数my_service_main,具体如何调用取决于开发人员。
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>) {
}
fn main() -> Result<(), windows_service::Error> {
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) {
}
}
fn run_service(arguments: Vec<OsString>) -> Result<(), windows_service::Error> {
let event_handler = move |control_event| -> ServiceControlHandlerResult {
match control_event {
ServiceControl::Stop => {
ServiceControlHandlerResult::NoError
}
ServiceControl::Interrogate => ServiceControlHandlerResult::NoError,
_ => ServiceControlHandlerResult::NotImplemented,
}
};
let status_handle = service_control_handler::register("myservice", event_handler)?;
Ok(())
}
更新服务状态,当系统启动实现windows服务的应用程序时,它会自动处于StartPending状态。应用程序需要完成初始化,获得ServiceStatusHandle(请参阅[service_control_handler::register])并转换到正在运行状态。如果服务的初始化时间很长,它应该立即告诉系统它需要多少时间来完成初始化,方法是发送StartPending状态,使用ServiceStatus::wait_hint估计时间,并在每次服务完成初始化步骤时增加ServiceStatus::checkpoint。在建议的ServiceStatus::wait_int过期之后,系统将尝试终止无法转换到“正在运行”状态的服务。当在其他未决状态与其对应的目标状态之间转换时,同样的概念也适用。请注意,克隆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) {
}
}
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,
}
};
let status_handle = service_control_handler::register("my_service_name", event_handler)?;
let next_status = ServiceStatus {
service_type: ServiceType::OWN_PROCESS,
current_state: ServiceState::Running,
controls_accepted: ServiceControlAccept::STOP,
exit_code: ServiceExitCode::Win32(0),
checkpoint: 0,
wait_hint: Duration::default(),
};
status_handle.set_service_status(next_status)?;
Ok(())
}
https://github.com/mullvad/windows-service-rs