Skip to main content

win_desktop_utils/
lib.rs

1//! Windows-first desktop utility helpers for Rust apps.
2//!
3//! `win-desktop-utils` provides small, focused helpers for common Windows desktop-app
4//! tasks without forcing consumers to work directly with raw Win32 shell, mutex, and
5//! known-folder APIs.
6//!
7//! # Scope
8//!
9//! This crate currently provides helpers for:
10//!
11//! - opening files and directories with the default shell handler
12//! - opening URLs
13//! - revealing items in Explorer
14//! - sending files or directories to the Recycle Bin
15//! - enforcing single-instance behavior
16//! - resolving per-user app-data directories
17//! - creating per-user app-data directories if needed
18//! - checking elevation and relaunching as admin
19//!
20//! This crate is intended for Windows desktop applications and utilities.
21//! Some functions launch external shell behavior or may trigger a UAC prompt.
22//! This crate supports Windows only.
23//!
24//! # Current API
25//!
26//! - [`open_with_default`]
27//! - [`open_url`]
28//! - [`reveal_in_explorer`]
29//! - [`move_to_recycle_bin`]
30//! - [`single_instance`]
31//! - [`roaming_app_data`]
32//! - [`local_app_data`]
33//! - [`ensure_roaming_app_data`]
34//! - [`ensure_local_app_data`]
35//! - [`is_elevated`]
36//! - [`restart_as_admin`]
37//!
38//! # Example
39//!
40//! ```
41//! fn main() -> Result<(), win_desktop_utils::Error> {
42//!     let _guard = match win_desktop_utils::single_instance("demo-app")? {
43//!         Some(guard) => guard,
44//!         None => {
45//!             println!("already running");
46//!             return Ok(());
47//!         }
48//!     };
49//!
50//!     let local = win_desktop_utils::ensure_local_app_data("demo-app")?;
51//!     assert!(local.ends_with("demo-app"));
52//!
53//!     Ok(())
54//! }
55//! ```
56//!
57//! # Behavior Notes
58//!
59//! - [`open_with_default`] requires a non-empty existing path.
60//! - [`open_url`] trims surrounding whitespace before delegating to the Windows shell.
61//! - [`reveal_in_explorer`] requires an existing path and launches `explorer.exe`.
62//! - [`move_to_recycle_bin`] requires an absolute existing path and uses `IFileOperation`
63//!   on a dedicated STA thread for recycle-bin behavior.
64//! - [`roaming_app_data`] and [`local_app_data`] resolve their base directories via
65//!   `SHGetKnownFolderPath`.
66//! - [`single_instance`] uses a `Local\...` named mutex, so the lock is scoped to the
67//!   current Windows session, and `app_id` cannot contain backslashes.
68//! - [`restart_as_admin`] starts a new elevated instance of the current executable,
69//!   does not terminate the current process, and rejects arguments containing NUL bytes.
70
71#[cfg(not(windows))]
72compile_error!("win-desktop-utils supports Windows only.");
73
74#[cfg(windows)]
75pub mod elevation;
76#[cfg(windows)]
77pub mod error;
78#[cfg(windows)]
79pub mod instance;
80#[cfg(windows)]
81pub mod paths;
82#[cfg(windows)]
83pub mod shell;
84
85#[cfg(windows)]
86pub use error::{Error, Result};
87
88#[cfg(windows)]
89pub use elevation::{is_elevated, restart_as_admin};
90#[cfg(windows)]
91pub use instance::{single_instance, InstanceGuard};
92#[cfg(windows)]
93pub use paths::{ensure_local_app_data, ensure_roaming_app_data, local_app_data, roaming_app_data};
94#[cfg(windows)]
95pub use shell::{move_to_recycle_bin, open_url, open_with_default, reveal_in_explorer};