use std::env::current_exe;
use std::ffi::{OsStr, OsString};
use std::io;
use std::path::Path;
use crate::convert::encode_escaped_os_str;
use crate::error::Error;
use crate::error::ErrorKind::*;
use crate::registry::OpenRegistryKey;
use crate::Result;
#[non_exhaustive]
pub struct AutoStart {
name: Box<OsStr>,
executable: Box<Path>,
arguments: Vec<OsString>,
}
impl AutoStart {
pub fn current_exe<N>(name: N) -> Result<Self>
where
N: AsRef<OsStr>,
{
let executable = current_exe().map_err(CurrentExecutable)?;
Ok(Self::new(name, executable))
}
#[inline]
pub fn new<N, E>(name: N, executable: E) -> Self
where
N: AsRef<OsStr>,
E: AsRef<Path>,
{
Self {
name: name.as_ref().into(),
executable: executable.as_ref().into(),
arguments: Vec::new(),
}
}
pub fn arguments<A>(&mut self, arguments: A)
where
A: IntoIterator,
A::Item: AsRef<OsStr>,
{
self.arguments = arguments
.into_iter()
.map(|a| a.as_ref().to_os_string())
.collect();
}
}
impl AutoStart {
fn registry_entry(&self) -> Result<String> {
let mut entry = String::new();
encode_escaped_os_str(&mut entry, self.executable.as_os_str())
.map_err(BadAutoStartExecutable)?;
for argument in &self.arguments {
entry.push(' ');
encode_escaped_os_str(&mut entry, argument).map_err(BadAutoStartArgument)?;
}
Ok(entry)
}
pub fn is_installed(&self) -> Result<bool> {
let key = OpenRegistryKey::current_user()
.open("Software\\Microsoft\\Windows\\CurrentVersion\\Run")
.map_err(OpenRegistryKey)?;
let path = match key.get_string(&self.name) {
Ok(path) => path,
Err(e) if e.kind() == io::ErrorKind::NotFound => return Ok(false),
Err(e) => return Err(Error::new(GetRegistryValue(e))),
};
Ok(self.registry_entry()?.as_str() == path)
}
pub fn install(&self) -> Result<()> {
let key = OpenRegistryKey::current_user()
.set_value()
.open("Software\\Microsoft\\Windows\\CurrentVersion\\Run")
.map_err(OpenRegistryKey)?;
key.set(&self.name, self.registry_entry()?)
.map_err(SetRegistryKey)?;
Ok(())
}
pub fn uninstall(&self) -> Result<()> {
let key = OpenRegistryKey::current_user()
.set_value()
.open("Software\\Microsoft\\Windows\\CurrentVersion\\Run")
.map_err(OpenRegistryKey)?;
key.delete(&self.name).map_err(DeleteRegistryKey)?;
Ok(())
}
}