#服务 #守护进程 #Windows #API 绑定

windows-service

一个库,提供管理和实现 Windows 服务的功能

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 日

#12Windows API

Download history 9488/week @ 2024-05-01 10358/week @ 2024-05-08 9746/week @ 2024-05-15 9623/week @ 2024-05-22 11195/week @ 2024-05-29 10052/week @ 2024-06-05 10219/week @ 2024-06-12 11140/week @ 2024-06-19 11074/week @ 2024-06-26 11221/week @ 2024-07-03 11759/week @ 2024-07-10 11638/week @ 2024-07-17 14343/week @ 2024-07-24 13285/week @ 2024-07-31 14148/week @ 2024-08-07 12635/week @ 2024-08-14

56,557 每月下载量
用于 24 个库 (20 个直接使用)

MIT/Apache

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