#[cfg(windows)]
use restart_manager::{RestartSession, ShutdownOptions};
#[cfg(windows)]
#[derive(Debug, thiserror::Error)]
enum InstallerError {
#[error("Restart Manager operation failed: {0}")]
RestartManager(#[from] restart_manager::Error),
#[error("file update failed: {0}")]
Update(#[from] std::io::Error),
}
#[cfg(windows)]
type InstallerResult<T = ()> = Result<T, InstallerError>;
#[cfg(windows)]
fn main() -> InstallerResult {
let Some(file) = std::env::args_os().nth(1) else {
eprintln!("usage: installer <file-to-update>");
return Ok(());
};
let mut session = RestartSession::new()?;
session.register_files([&file])?;
let report = session.affected_applications()?;
eprintln!("reboot reasons: {:?}", report.reboot_reasons());
for application in &report {
eprintln!(
"{} (restartable: {})",
application.display_name().to_string_lossy(),
application.is_restartable(),
);
}
let pending = session
.shutdown_with_options(ShutdownOptions::new().with_require_restart_registration(true));
let update_result = if pending.shutdown_outcome().is_success() {
replace_registered_file(&file)
} else {
Ok(())
};
let completion = pending.restart();
let outcome = completion.outcome().clone();
let end_result = completion.end();
outcome.shutdown_outcome().clone().into_result()?;
update_result?;
outcome
.restart_outcome()
.expect("this recipe always attempts restart")
.clone()
.into_result()?;
end_result?;
Ok(())
}
#[cfg(windows)]
fn replace_registered_file(_file: &std::ffi::OsStr) -> std::io::Result<()> {
Ok(())
}
#[cfg(not(windows))]
fn main() {
eprintln!("this example requires Windows");
}