UniServiceManager

Struct UniServiceManager 

Source
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

Source

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?
examples/manager.rs (line 17)
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}
Source

pub fn capabilities() -> ServiceCapabilities

Gets the capabilities of the underlying platform service manager.

Examples found in repository?
examples/manager.rs (line 15)
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}
Source

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.

Source

pub fn is_user_service(&self) -> bool

true if the service is a user service, false if it is a system service.

Source

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.

Source

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?
examples/manager.rs (line 36)
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}
Source

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.

Source

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.

Source

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?
examples/manager.rs (line 53)
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}
Source

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.

Source

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.

Source

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?
examples/manager.rs (line 40)
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}
Source

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.

Source

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?
examples/manager.rs (line 49)
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}
Source

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.

Source

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.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.