我尝试使用winapi编写一个Windows服务
如何使用main函数的“heventlog”传递给service_main
在其他语言中,我们可以使用全局变量。 Rust 中如何处理这种情况?
代码
use std::sync::{Arc, Mutex};
use windows::core::{w, PWSTR};
use windows::Win32::Foundation::HANDLE;
use windows::Win32::System::Services::{
RegisterServiceCtrlHandlerW, SetServiceStatus, StartServiceCtrlDispatcherW,
SERVICE_ACCEPT_STOP, SERVICE_CONTROL_STOP, SERVICE_RUNNING, SERVICE_START_PENDING,
SERVICE_STATUS, SERVICE_STOPPED, SERVICE_TABLE_ENTRYW, SERVICE_WIN32_OWN_PROCESS,
};
unsafe extern "system" fn service_control_handler(dwcontrol: u32) {
match dwcontrol {
SERVICE_CONTROL_STOP => return,
_ => {}
}
}
unsafe extern "system" fn service_main(_dwnumservicesargs: u32, _lpserviceargvectors: *mut PWSTR) {
// How to use heventlog
let mut lpservicestatus = SERVICE_STATUS {
dwServiceType: SERVICE_WIN32_OWN_PROCESS,
dwCurrentState: SERVICE_START_PENDING,
dwControlsAccepted: SERVICE_ACCEPT_STOP,
dwWin32ExitCode: 0,
dwServiceSpecificExitCode: 0,
dwCheckPoint: 0,
dwWaitHint: 0,
};
let lpservicename = w!("Demo Service");
let hservicestatus =
RegisterServiceCtrlHandlerW(lpservicename, Some(service_control_handler)).unwrap();
lpservicestatus.dwCurrentState = SERVICE_RUNNING;
SetServiceStatus(hservicestatus, &mut lpservicestatus).unwrap();
}
fn main() {
use windows::Win32::System::EventLog::RegisterEventSourceW;
let heventlog = unsafe { RegisterEventSourceW(None, w!("Demo Service")) }.unwrap();
let heventlog: Arc<Mutex<HANDLE>> = Arc::new(Mutex::new(heventlog));
// How heventlog is passed to service_main
let mut lp_service_name = "Demo Service\0".encode_utf16().collect::<Vec<u16>>();
let lp_service_name = PWSTR::from_raw(lp_service_name.as_mut_ptr());
let lpservicestarttable = [
SERVICE_TABLE_ENTRYW {
lpServiceName: lp_service_name,
lpServiceProc: Some(service_main),
},
SERVICE_TABLE_ENTRYW {
lpServiceName: PWSTR::null(),
lpServiceProc: None,
},
]
.as_ptr();
unsafe { StartServiceCtrlDispatcherW(lpservicestarttable) }.unwrap();
}
service_main可以使用heventlog来记录日志
Rust 中也可以有全局变量:
use std::sync::OnceLock;
static H_EVENT_LOG: OnceLock<HANDLE> = OnceLock::new();
unsafe extern "system" fn service_main(_dwnumservicesargs: u32, _lpserviceargvectors: *mut PWSTR) {
// use H_EVENT_LOG.get()
// ...
}
fn main() {
let heventlog = unsafe { RegisterEventSourceW(None, w!("Demo Service")) }.unwrap();
H_EVENT_LOG.set(heventlog).unwrap();
// ...
}