Rust编写Windows服务

server/2024/9/22 18:14:14/

文章目录

  • Rust编写Windows服务
    • 一:Windows服务程序大致原理
    • 二:Rust中编写windows服务
    • 三:具体实例

Rust编写Windows服务

编写Windows服务可选语言很多, 其中C#最简单。本着练手Rust语言,尝试用Rust编写一个服务。

一:Windows服务程序大致原理

参考官网C/C++创建服务流程
https://learn.microsoft.com/zh-cn/windows/win32/services/service-program-tasks

  • 编写服务程序的main函数
    1. main函数中,填充数据结构 DispatchTable: [[服务名,ServiceMain函数], [NULL, NULL]]
    2. 调用StartServiceCtrlDispatcher( DispatchTable )
int __cdecl _tmain(int argc, TCHAR *argv[])
{ SERVICE_TABLE_ENTRY DispatchTable[] = { { SVCNAME, (LPSERVICE_MAIN_FUNCTION) SvcMain }, { NULL, NULL } }; if (!StartServiceCtrlDispatcher( DispatchTable )) { SvcReportEvent(TEXT("StartServiceCtrlDispatcher")); } 
} 
  • 编写 ServiceMain 函数
    1. 注册控制处理函数 RegisterServiceCtrlHandler(SvcCtrlHandler )
    2. 设置服务状态,SERVICE_START_PENDING
    3. 做一些预备工作,比如初始化日志/注册事件等
    4. 设置服务状态,SERVICE_START_RUNNING
    5. 开始loop处理我们自己的代码(loop循环中可以接受3中注册的事件,当通知停止时退出循环)
  • 编写控件处理程序函数
    1. 接受事件管理器发送的消息并处理,比如收到SERVICE_CONTROL_STOP时,使用3中注册的事件句柄发送停止事件

windows_38">二:Rust中编写windows服务

借用第三方库 windows-service = "0.7.0"
https://crates.io/crates/windows-service
参考windows-service中ping-service示例提取了一个模板,只有替换编写两处/* */代码

rust">use std::{ffi::OsString,sync::mpsc,time::Duration,
};
use windows_service::{define_windows_service,service::{ServiceControl, ServiceControlAccept, ServiceExitCode, ServiceState, ServiceStatus,ServiceType,},service_control_handler::{self, ServiceControlHandlerResult},service_dispatcher,
};static SERVICE_NAME: &str = "Rust Demo Service";fn main() -> Result<(), windows_service::Error> {service_dispatcher::start(SERVICE_NAME, ffi_service_main)?;Ok(())
}define_windows_service!(ffi_service_main, my_service_main);fn my_service_main(arguments: Vec<OsString>) {let _ = arguments;/*这里服务还没开始, 可以填写初始化日志文件等操作*/let (shutdown_tx, shutdown_rx) = mpsc::channel();// 对应SvcCtrlHandlerlet _event_handler = move |control_event| -> ServiceControlHandlerResult {match control_event {ServiceControl::Interrogate => ServiceControlHandlerResult::NoError,// 处理停止事件ServiceControl::Stop => {shutdown_tx.send(()).unwrap();ServiceControlHandlerResult::NoError}// 其他用户事件都当作停止事件处理ServiceControl::UserEvent(code) => {if code.to_raw() == 130 {shutdown_tx.send(()).unwrap();}ServiceControlHandlerResult::NoError}_ => ServiceControlHandlerResult::NotImplemented,}};let status_handle = service_control_handler::register(SERVICE_NAME, _event_handler);let status_handle = status_handle.unwrap();let _ = status_handle.set_service_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(),process_id: None,});loop {/*这里写自己的代码逻辑,下面时处理一次循环后睡眠5秒,若是接受到停止等消息退出循环*/match shutdown_rx.recv_timeout(Duration::from_secs(5)) {Ok(_) | Err(mpsc::RecvTimeoutError::Disconnected) => break,Err(mpsc::RecvTimeoutError::Timeout) => (),}}let _ = status_handle.set_service_status(ServiceStatus {service_type: ServiceType::OWN_PROCESS,current_state: ServiceState::Stopped,controls_accepted: ServiceControlAccept::empty(),exit_code: ServiceExitCode::Win32(0),checkpoint: 0,wait_hint: Duration::default(),process_id: None,});
}

三:具体实例

笔记本策略经常恢复到合上盖子睡眠功能,写个小服务定时设置合上盖子不做任何操作
逻辑比较简单,定时调用WinAPI函数CallNtPowerInformation获取配置信息,不符合当前设置执行修改
完整如下

rust">use std::{ffi::{c_void, OsString},sync::mpsc,time::Duration,
};
use windows::Win32::{Foundation::STATUS_SUCCESS, System::Power::{CallNtPowerInformation, POWER_INFORMATION_LEVEL, SYSTEM_POWER_POLICY}};
use windows_service::{define_windows_service,service::{ServiceControl, ServiceControlAccept, ServiceExitCode, ServiceState, ServiceStatus,ServiceType,},service_control_handler::{self, ServiceControlHandlerResult},service_dispatcher,
};static SERVICE_NAME: &str = "Power Lid Service";fn main() -> Result<(), windows_service::Error> {service_dispatcher::start(SERVICE_NAME, ffi_service_main)?;Ok(())
}define_windows_service!(ffi_service_main, my_service_main);fn my_service_main(arguments: Vec<OsString>) {let _ = arguments;let (shutdown_tx, shutdown_rx) = mpsc::channel();let _event_handler = move |control_event| -> ServiceControlHandlerResult {match control_event {ServiceControl::Interrogate => ServiceControlHandlerResult::NoError,ServiceControl::Stop => {shutdown_tx.send(()).unwrap();ServiceControlHandlerResult::NoError}ServiceControl::UserEvent(code) => {if code.to_raw() == 130 {shutdown_tx.send(()).unwrap();}ServiceControlHandlerResult::NoError}_ => ServiceControlHandlerResult::NotImplemented,}};let status_handle = service_control_handler::register(SERVICE_NAME, _event_handler);let status_handle = status_handle.unwrap();let _ = status_handle.set_service_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(),process_id: None,});loop {unsafe {let mut a: SYSTEM_POWER_POLICY = std::mem::zeroed();let status = CallNtPowerInformation(POWER_INFORMATION_LEVEL { 0: 8 },None,0,Some(&mut a as *mut SYSTEM_POWER_POLICY as *mut c_void),size_of::<SYSTEM_POWER_POLICY>() as u32,);if status != STATUS_SUCCESS {println!("获取电源状态失败: {:x} !", status.0);return;}if a.LidClose.Action.0 == 0 {println!("状态已为0, 忽略");return;} else {println!("状态为{:x}", a.LidClose.Action.0);a.LidClose.Action.0 = 0;let status = CallNtPowerInformation(POWER_INFORMATION_LEVEL { 0: 0 },Some(&mut a as *mut SYSTEM_POWER_POLICY as *mut c_void),size_of::<SYSTEM_POWER_POLICY>() as u32,None,0,);if status != STATUS_SUCCESS {println!("设置ac电源状态失败: {:x} !", status.0);return;} else {println!("设置AC电源状态成功");}let status = CallNtPowerInformation(POWER_INFORMATION_LEVEL { 0: 1 },Some(&mut a as *mut SYSTEM_POWER_POLICY as *mut c_void),size_of::<SYSTEM_POWER_POLICY>() as u32,None,0,);if status != STATUS_SUCCESS {println!("设置dc电源状态失败: {:x} !", status.0);return;} else {println!("设置DC电源状态成功");}}}match shutdown_rx.recv_timeout(Duration::from_secs(5)) {Ok(_) | Err(mpsc::RecvTimeoutError::Disconnected) => break,Err(mpsc::RecvTimeoutError::Timeout) => (),}}let _ = status_handle.set_service_status(ServiceStatus {service_type: ServiceType::OWN_PROCESS,current_state: ServiceState::Stopped,controls_accepted: ServiceControlAccept::empty(),exit_code: ServiceExitCode::Win32(0),checkpoint: 0,wait_hint: Duration::default(),process_id: None,});
}

http://www.ppmy.cn/server/120398.html

相关文章

第k个排列 - 华为OD统一考试(E卷)

2024华为OD机试(E卷+D卷+C卷)最新题库【超值优惠】Java/Python/C++合集 题目描述 给定参数n,从1到n会有n个整数:1,2,3,.,n,这n个数字共有 n!种排列。按大小顺序升序列出所有排列情况,并-一标记,当n=3时,所有排列如下: “123” “132” “213” “231” “312” “…

「数组」十大排序:精讲与分析(C++)

概述 截止目前&#xff0c;我们已经讲解并分析了十种最常见的排序算法&#xff0c;下附对应文章链接和全体Code。 链接 「数组」冒泡排序|选择排序|插入排序 / 及优化方案&#xff08;C&#xff09; 「数组」归并排序 / if语句优化|小区间插入优化&#xff08;C&#xff09…

CTFShow-反序列化

一些基础&#xff1a; private变量会被序列化为&#xff1a;\x00类名\x00变量名 protected变量会被序列化为: \x00*\x00变量名 public变量会被序列化为&#xff1a;变量名 __sleep() //在对象被序列化之前运行 * __wakeup() //将在反序列化之后立即调用&#xff08;当反序列化时…

天安门广场预约分析

首先&#xff0c;我们进入到首页&#xff0c;https://yuyue.tamgw.beijing.gov.cn/index.html&#xff0c;我们选择个人预约信息。 第一个比较重要的参数playDate&#xff0c;就是预约日期&#xff0c;一般可以预约未来1-7天的不同时间段&#xff0c;这里我们选择好固定的日期…

鸿蒙OpenHarmony【轻量系统芯片移植】轻量系统STM32F407芯片移植案例

轻量系统STM32F407芯片移植案例 介绍基于STM32F407IGT6芯片在拓维信息[Niobe407]开发板上移植OpenHarmony LiteOS-M轻量系统&#xff0c;提供交通、工业领域开发板解决方案。移植架构采用Board与SoC分离方案&#xff0c;使用arm gcc工具链Newlib C库&#xff0c;实现了lwip、l…

SQL Server 2022的数据类型

新书速览|SQL Server 2022从入门到精通&#xff1a;视频教学超值版_sql server 2022 出版社-CSDN博客 《SQL Server 2022从入门到精通&#xff08;视频教学超值版&#xff09;&#xff08;数据库技术丛书&#xff09;》(王英英)【摘要 书评 试读】- 京东图书 (jd.com) 数据类…

docker创建rabbitmq容器

创建rabbitmq容器 1.docker导入镜像 2.写docker-compose文件 并创建容器 3.访问15672端口 账号和密码都是guest

演讲比赛流程管理系统(简陋版)

Person.h #pragma once #include<iostream> using namespace std; #include<vector> #include<string> class Person { public:Person() {};// 构造函数,初始化Person(string name, int id);// 获取姓名string& getName();// 给姓名赋值void setName(co…