pub struct UniServiceManager { /* private fields */ }Expand description
A service manager to manage services on the current system. It uses platform-specific implementations behind the scenes to perform the actual service management, but provides a unified interface regardless of the platform.
Implementations§
Source§impl UniServiceManager
impl UniServiceManager
Sourcepub fn new(
name: impl Into<OsString>,
prefix: impl Into<OsString>,
user: bool,
) -> UniResult<Self, ServiceErrKind>
pub fn new( name: impl Into<OsString>, prefix: impl Into<OsString>, user: bool, ) -> UniResult<Self, ServiceErrKind>
Creates a new service manager for the given service name. The prefix is a java-style
reverse domain name prefix (e.g. com.example.) and is only used on macOS (ignored on other
platforms). If user is true, the service applies directly to the current user only.
On Windows, user level services require administrator privileges to manage and won’t start
until the first logon.
Examples found in repository?
8fn run(
9 service_name: &str,
10 display_name: &str,
11 description: &str,
12) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
13 // Windows user services require a new logon before they can be started, so we will use a system service on Windows.
14 // NOTE: Windows services always require elevated privileges to install, so run this example as administrator.
15 let user = !UniServiceManager::capabilities()
16 .contains(ServiceCapabilities::USER_SERVICES_REQUIRE_NEW_LOGON);
17 let user_manager = UniServiceManager::new(service_name, "com.example.", user)?;
18
19 let mut bin_path = std::env::current_exe().unwrap();
20 bin_path.set_file_name(service_name);
21
22 if !bin_path.exists() {
23 return Err(format!(
24 "Executable not found: {}. Make sure to build the service examples first.",
25 bin_path.display()
26 )
27 .into());
28 }
29
30 let spec = ServiceSpec::new(bin_path)
31 .arg("service")?
32 .display_name(display_name)?
33 .description(description)?;
34
35 print!("Installing service '{service_name}'...",);
36 user_manager.install_and_wait(&spec, TIMEOUT)?;
37 println!("done");
38
39 print!("Starting service '{service_name}'...");
40 user_manager.start_and_wait(TIMEOUT)?;
41 println!("done");
42
43 io::stdout().flush()?;
44 println!("Press Enter to stop the service...");
45 let mut buffer = String::new();
46 io::stdin().read_line(&mut buffer)?;
47
48 print!("Stopping service '{service_name}'...");
49 user_manager.stop_and_wait(TIMEOUT)?;
50 println!("done");
51
52 print!("Uninstalling service '{service_name}'...");
53 user_manager.uninstall_and_wait(TIMEOUT)?;
54 println!("done");
55
56 Ok(())
57}Sourcepub fn capabilities() -> ServiceCapabilities
pub fn capabilities() -> ServiceCapabilities
Gets the capabilities of the underlying platform service manager.
Examples found in repository?
8fn run(
9 service_name: &str,
10 display_name: &str,
11 description: &str,
12) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
13 // Windows user services require a new logon before they can be started, so we will use a system service on Windows.
14 // NOTE: Windows services always require elevated privileges to install, so run this example as administrator.
15 let user = !UniServiceManager::capabilities()
16 .contains(ServiceCapabilities::USER_SERVICES_REQUIRE_NEW_LOGON);
17 let user_manager = UniServiceManager::new(service_name, "com.example.", user)?;
18
19 let mut bin_path = std::env::current_exe().unwrap();
20 bin_path.set_file_name(service_name);
21
22 if !bin_path.exists() {
23 return Err(format!(
24 "Executable not found: {}. Make sure to build the service examples first.",
25 bin_path.display()
26 )
27 .into());
28 }
29
30 let spec = ServiceSpec::new(bin_path)
31 .arg("service")?
32 .display_name(display_name)?
33 .description(description)?;
34
35 print!("Installing service '{service_name}'...",);
36 user_manager.install_and_wait(&spec, TIMEOUT)?;
37 println!("done");
38
39 print!("Starting service '{service_name}'...");
40 user_manager.start_and_wait(TIMEOUT)?;
41 println!("done");
42
43 io::stdout().flush()?;
44 println!("Press Enter to stop the service...");
45 let mut buffer = String::new();
46 io::stdin().read_line(&mut buffer)?;
47
48 print!("Stopping service '{service_name}'...");
49 user_manager.stop_and_wait(TIMEOUT)?;
50 println!("done");
51
52 print!("Uninstalling service '{service_name}'...");
53 user_manager.uninstall_and_wait(TIMEOUT)?;
54 println!("done");
55
56 Ok(())
57}Sourcepub fn fully_qualified_name(&self) -> Cow<'_, OsStr>
pub fn fully_qualified_name(&self) -> Cow<'_, OsStr>
Gets the fully qualified name of the service. Note that Windows user services have a dynamic name that changes between sessions.
Sourcepub fn is_user_service(&self) -> bool
pub fn is_user_service(&self) -> bool
true if the service is a user service, false if it is a system service.
Sourcepub fn install(&self, spec: &ServiceSpec) -> UniResult<(), ServiceErrKind>
pub fn install(&self, spec: &ServiceSpec) -> UniResult<(), ServiceErrKind>
Installs the service. The program is the path to the executable to run when the service starts.
The args are the arguments to pass to the executable. The display_name is the name to display
to the user. The desc is the description of the service. After the method returns successfully, the
service may or may not be installed yet, as this is platform-dependent. An error is returned if the
service is already installed or if the installation fails.
Sourcepub fn install_and_wait(
&self,
spec: &ServiceSpec,
timeout: Duration,
) -> UniResult<ServiceStatus, ServiceErrKind>
pub fn install_and_wait( &self, spec: &ServiceSpec, timeout: Duration, ) -> UniResult<ServiceStatus, ServiceErrKind>
Installs the service and waits for it to reach the expected status. The timeout is the maximum time
to wait for the service to reach that status. The expected status is Running if autostart is enabled and the
service starts immediately after install, otherwise Stopped. The current status is returned when successful.
Examples found in repository?
8fn run(
9 service_name: &str,
10 display_name: &str,
11 description: &str,
12) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
13 // Windows user services require a new logon before they can be started, so we will use a system service on Windows.
14 // NOTE: Windows services always require elevated privileges to install, so run this example as administrator.
15 let user = !UniServiceManager::capabilities()
16 .contains(ServiceCapabilities::USER_SERVICES_REQUIRE_NEW_LOGON);
17 let user_manager = UniServiceManager::new(service_name, "com.example.", user)?;
18
19 let mut bin_path = std::env::current_exe().unwrap();
20 bin_path.set_file_name(service_name);
21
22 if !bin_path.exists() {
23 return Err(format!(
24 "Executable not found: {}. Make sure to build the service examples first.",
25 bin_path.display()
26 )
27 .into());
28 }
29
30 let spec = ServiceSpec::new(bin_path)
31 .arg("service")?
32 .display_name(display_name)?
33 .description(description)?;
34
35 print!("Installing service '{service_name}'...",);
36 user_manager.install_and_wait(&spec, TIMEOUT)?;
37 println!("done");
38
39 print!("Starting service '{service_name}'...");
40 user_manager.start_and_wait(TIMEOUT)?;
41 println!("done");
42
43 io::stdout().flush()?;
44 println!("Press Enter to stop the service...");
45 let mut buffer = String::new();
46 io::stdin().read_line(&mut buffer)?;
47
48 print!("Stopping service '{service_name}'...");
49 user_manager.stop_and_wait(TIMEOUT)?;
50 println!("done");
51
52 print!("Uninstalling service '{service_name}'...");
53 user_manager.uninstall_and_wait(TIMEOUT)?;
54 println!("done");
55
56 Ok(())
57}Sourcepub fn install_if_needed_and_start(
&self,
spec: &ServiceSpec,
timeout: Duration,
) -> UniResult<(), ServiceErrKind>
pub fn install_if_needed_and_start( &self, spec: &ServiceSpec, timeout: Duration, ) -> UniResult<(), ServiceErrKind>
Installs the service if it is not already installed and starts it. The timeout is the maximum time
to wait for the service to reach the expected status. The expected status is Running if autostart is enabled and the
service starts immediately after install, otherwise Stopped. The current status is returned when successful.
Sourcepub fn uninstall(&self) -> UniResult<(), ServiceErrKind>
pub fn uninstall(&self) -> UniResult<(), ServiceErrKind>
Uninstalls the service. After the method returns successfully, the service may or may not be uninstalled yet, as this is platform-dependent. An error is returned if the service is not installed, if the service is not stopped, or if the uninstallation fails.
Sourcepub fn uninstall_and_wait(
&self,
timeout: Duration,
) -> UniResult<(), ServiceErrKind>
pub fn uninstall_and_wait( &self, timeout: Duration, ) -> UniResult<(), ServiceErrKind>
Uninstalls the service and waits for it to reach the expected status of NotInstalled.
The timeout is the maximum time to wait for the service to reach that status.
Examples found in repository?
8fn run(
9 service_name: &str,
10 display_name: &str,
11 description: &str,
12) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
13 // Windows user services require a new logon before they can be started, so we will use a system service on Windows.
14 // NOTE: Windows services always require elevated privileges to install, so run this example as administrator.
15 let user = !UniServiceManager::capabilities()
16 .contains(ServiceCapabilities::USER_SERVICES_REQUIRE_NEW_LOGON);
17 let user_manager = UniServiceManager::new(service_name, "com.example.", user)?;
18
19 let mut bin_path = std::env::current_exe().unwrap();
20 bin_path.set_file_name(service_name);
21
22 if !bin_path.exists() {
23 return Err(format!(
24 "Executable not found: {}. Make sure to build the service examples first.",
25 bin_path.display()
26 )
27 .into());
28 }
29
30 let spec = ServiceSpec::new(bin_path)
31 .arg("service")?
32 .display_name(display_name)?
33 .description(description)?;
34
35 print!("Installing service '{service_name}'...",);
36 user_manager.install_and_wait(&spec, TIMEOUT)?;
37 println!("done");
38
39 print!("Starting service '{service_name}'...");
40 user_manager.start_and_wait(TIMEOUT)?;
41 println!("done");
42
43 io::stdout().flush()?;
44 println!("Press Enter to stop the service...");
45 let mut buffer = String::new();
46 io::stdin().read_line(&mut buffer)?;
47
48 print!("Stopping service '{service_name}'...");
49 user_manager.stop_and_wait(TIMEOUT)?;
50 println!("done");
51
52 print!("Uninstalling service '{service_name}'...");
53 user_manager.uninstall_and_wait(TIMEOUT)?;
54 println!("done");
55
56 Ok(())
57}Sourcepub fn stop_if_needed_and_uninstall(
&self,
timeout: Duration,
) -> UniResult<(), ServiceErrKind>
pub fn stop_if_needed_and_uninstall( &self, timeout: Duration, ) -> UniResult<(), ServiceErrKind>
Stops the service if it is running and uninstalls it. If the service is already stopped, it will be uninstalled
without further action. The timeout is the maximum time to wait for the service to reach each expected status.
Sourcepub fn start(&self) -> UniResult<(), ServiceErrKind>
pub fn start(&self) -> UniResult<(), ServiceErrKind>
Starts the service. After the method returns successfully, the service may or may not be started yet, as this is platform-dependent. An error is returned if the service is not stopped or if the starting fails.
Sourcepub fn start_and_wait(&self, timeout: Duration) -> UniResult<(), ServiceErrKind>
pub fn start_and_wait(&self, timeout: Duration) -> UniResult<(), ServiceErrKind>
Starts the service and waits for it to reach the expected status of Running.
The timeout is the maximum time to wait for the service to reach that status.
Examples found in repository?
8fn run(
9 service_name: &str,
10 display_name: &str,
11 description: &str,
12) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
13 // Windows user services require a new logon before they can be started, so we will use a system service on Windows.
14 // NOTE: Windows services always require elevated privileges to install, so run this example as administrator.
15 let user = !UniServiceManager::capabilities()
16 .contains(ServiceCapabilities::USER_SERVICES_REQUIRE_NEW_LOGON);
17 let user_manager = UniServiceManager::new(service_name, "com.example.", user)?;
18
19 let mut bin_path = std::env::current_exe().unwrap();
20 bin_path.set_file_name(service_name);
21
22 if !bin_path.exists() {
23 return Err(format!(
24 "Executable not found: {}. Make sure to build the service examples first.",
25 bin_path.display()
26 )
27 .into());
28 }
29
30 let spec = ServiceSpec::new(bin_path)
31 .arg("service")?
32 .display_name(display_name)?
33 .description(description)?;
34
35 print!("Installing service '{service_name}'...",);
36 user_manager.install_and_wait(&spec, TIMEOUT)?;
37 println!("done");
38
39 print!("Starting service '{service_name}'...");
40 user_manager.start_and_wait(TIMEOUT)?;
41 println!("done");
42
43 io::stdout().flush()?;
44 println!("Press Enter to stop the service...");
45 let mut buffer = String::new();
46 io::stdin().read_line(&mut buffer)?;
47
48 print!("Stopping service '{service_name}'...");
49 user_manager.stop_and_wait(TIMEOUT)?;
50 println!("done");
51
52 print!("Uninstalling service '{service_name}'...");
53 user_manager.uninstall_and_wait(TIMEOUT)?;
54 println!("done");
55
56 Ok(())
57}Sourcepub fn stop(&self) -> UniResult<(), ServiceErrKind>
pub fn stop(&self) -> UniResult<(), ServiceErrKind>
Stops the service. After the method returns successfully, the service may or may not be stopped yet, as this is platform-dependent. An error is returned if the service is not running or if the stopping fails.
Sourcepub fn stop_and_wait(&self, timeout: Duration) -> UniResult<(), ServiceErrKind>
pub fn stop_and_wait(&self, timeout: Duration) -> UniResult<(), ServiceErrKind>
Stops the service and waits for it to reach the expected status of Stopped.
The timeout is the maximum time to wait for the service to reach that status.
Examples found in repository?
8fn run(
9 service_name: &str,
10 display_name: &str,
11 description: &str,
12) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
13 // Windows user services require a new logon before they can be started, so we will use a system service on Windows.
14 // NOTE: Windows services always require elevated privileges to install, so run this example as administrator.
15 let user = !UniServiceManager::capabilities()
16 .contains(ServiceCapabilities::USER_SERVICES_REQUIRE_NEW_LOGON);
17 let user_manager = UniServiceManager::new(service_name, "com.example.", user)?;
18
19 let mut bin_path = std::env::current_exe().unwrap();
20 bin_path.set_file_name(service_name);
21
22 if !bin_path.exists() {
23 return Err(format!(
24 "Executable not found: {}. Make sure to build the service examples first.",
25 bin_path.display()
26 )
27 .into());
28 }
29
30 let spec = ServiceSpec::new(bin_path)
31 .arg("service")?
32 .display_name(display_name)?
33 .description(description)?;
34
35 print!("Installing service '{service_name}'...",);
36 user_manager.install_and_wait(&spec, TIMEOUT)?;
37 println!("done");
38
39 print!("Starting service '{service_name}'...");
40 user_manager.start_and_wait(TIMEOUT)?;
41 println!("done");
42
43 io::stdout().flush()?;
44 println!("Press Enter to stop the service...");
45 let mut buffer = String::new();
46 io::stdin().read_line(&mut buffer)?;
47
48 print!("Stopping service '{service_name}'...");
49 user_manager.stop_and_wait(TIMEOUT)?;
50 println!("done");
51
52 print!("Uninstalling service '{service_name}'...");
53 user_manager.uninstall_and_wait(TIMEOUT)?;
54 println!("done");
55
56 Ok(())
57}Sourcepub fn status(&self) -> UniResult<ServiceStatus, ServiceErrKind>
pub fn status(&self) -> UniResult<ServiceStatus, ServiceErrKind>
Gets the current status of the service. It returns an error if the service is not installed or if the status cannot be determined.
Sourcepub fn wait_for_status(
&self,
desired_status: ServiceStatus,
timeout: Duration,
) -> UniResult<(), ServiceErrKind>
pub fn wait_for_status( &self, desired_status: ServiceStatus, timeout: Duration, ) -> UniResult<(), ServiceErrKind>
Waits for the service to reach the desired status. It returns an error if the service is not installed the status cannot be determined, or if the service does not reach the desired status before the timeout.