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}; use futures; use futures::FutureExt; use actix_web::{get, rt, web, App, HttpServer, Responder}; windows_service::define_windows_service!(ffi_service_main, my_service_main); #[get("/{name}")] async fn greet_person(name: web::Path) -> impl Responder { format!("Hello {name}!") } fn my_service_main(arguments: Vec) { if let Err(_e) = run_service(arguments) { // Handle errors in some way. } } 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. windows_service::service_dispatcher::start("myservice", ffi_service_main)?; Ok(()) } fn run_service(_arguments: Vec) -> windows_service::Result<()> { let sys = rt::System::new(); let _result = sys.block_on(HttpServer::new(|| { App::new() .route("/", web::get().to(|| async { "Hello World!" })) .service(greet_person) }) .bind(("127.0.0.1", 8080)) .unwrap() .run()); let (mut send_stop, recv_stop) = { //let (p, c) = futures::sync::oneshot::channel::<()>(); let (p, c) = futures::channel::oneshot::channel::<()>(); (Some(p), c) }; let event_handler = move |control_event| -> ServiceControlHandlerResult { match control_event { ServiceControl::Interrogate => ServiceControlHandlerResult::NoError, ServiceControl::Stop => { send_stop.take().unwrap().send(()).unwrap(); 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(), process_id: Some(0) }; // Tell the system that the service is running now status_handle.set_service_status(next_status)?; // Do some work actix_rt::spawn(recv_stop.map(move |_| { 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: Some(0) }).unwrap(); actix_rt::System::current().stop() }).map(|_| ())); sys.run().unwrap(); Ok(()) }