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 files and directories with explicit shell verbs
13//! - opening URLs
14//! - revealing items in Explorer
15//! - sending files or directories to the Recycle Bin
16//! - creating Windows `.lnk` and `.url` shortcuts
17//! - enforcing single-instance behavior
18//! - resolving per-user app-data directories
19//! - creating per-user app-data directories if needed
20//! - checking elevation and relaunching as admin
21//!
22//! This crate is intended for Windows desktop applications and utilities.
23//! Some functions launch external shell behavior or may trigger a UAC prompt.
24//! This crate supports Windows only.
25//!
26//! # Current API
27//!
28//! - [`open_with_default`]
29//! - [`open_with_verb`]
30//! - [`show_properties`]
31//! - [`print_with_default`]
32//! - [`open_url`]
33//! - [`reveal_in_explorer`]
34//! - [`open_containing_folder`]
35//! - [`move_to_recycle_bin`]
36//! - [`move_paths_to_recycle_bin`]
37//! - [`empty_recycle_bin`]
38//! - [`empty_recycle_bin_for_root`]
39//! - [`create_shortcut`]
40//! - [`create_url_shortcut`]
41//! - [`single_instance`]
42//! - [`single_instance_with_scope`]
43//! - [`single_instance_with_options`]
44//! - [`roaming_app_data`]
45//! - [`local_app_data`]
46//! - [`ensure_roaming_app_data`]
47//! - [`ensure_local_app_data`]
48//! - [`is_elevated`]
49//! - [`restart_as_admin`]
50//! - [`run_as_admin`]
51//! - [`run_with_verb`]
52//! - [`InstanceScope`]
53//! - [`SingleInstanceOptions`]
54//! - [`ShortcutOptions`]
55//! - [`ShortcutIcon`]
56//!
57//! # Example
58//!
59//! ```
60//! fn main() -> Result<(), win_desktop_utils::Error> {
61//! let _guard = match win_desktop_utils::single_instance("demo-app")? {
62//! Some(guard) => guard,
63//! None => {
64//! println!("already running");
65//! return Ok(());
66//! }
67//! };
68//!
69//! let local = win_desktop_utils::ensure_local_app_data("demo-app")?;
70//! assert!(local.ends_with("demo-app"));
71//!
72//! Ok(())
73//! }
74//! ```
75//!
76//! # Behavior Notes
77//!
78//! - [`open_with_default`] requires a non-empty existing path.
79//! - [`open_with_verb`] uses `ShellExecuteW` with the requested shell verb.
80//! - [`show_properties`] and [`print_with_default`] are small shell-verb wrappers.
81//! - [`open_url`] trims surrounding whitespace before delegating to the Windows shell.
82//! - [`reveal_in_explorer`] requires an existing path and launches `explorer.exe`.
83//! - [`open_containing_folder`] opens the existing path's parent directory.
84//! - [`move_to_recycle_bin`] requires an absolute existing path and uses `IFileOperation`
85//! on a dedicated STA thread for recycle-bin behavior.
86//! - [`move_paths_to_recycle_bin`] validates all paths before starting one shell
87//! recycle-bin operation.
88//! - [`empty_recycle_bin`] permanently empties the Recycle Bin without showing shell UI.
89//! - [`create_shortcut`] uses `IShellLinkW` on a dedicated STA thread.
90//! - [`roaming_app_data`] and [`local_app_data`] resolve their base directories via
91//! `SHGetKnownFolderPath`.
92//! - [`single_instance`] uses a `Local\...` named mutex, so the lock is scoped to the
93//! current Windows session, and `app_id` cannot contain backslashes.
94//! - [`single_instance_with_scope`] can opt into either the current-session or global
95//! mutex namespace.
96//! - [`restart_as_admin`] starts a new elevated instance of the current executable,
97//! does not terminate the current process, and rejects arguments containing NUL bytes.
98//! - [`run_as_admin`] and [`run_with_verb`] launch arbitrary commands through
99//! `ShellExecuteW`.
100
101#[cfg(not(windows))]
102compile_error!("win-desktop-utils supports Windows only.");
103
104#[cfg(windows)]
105pub mod elevation;
106#[cfg(windows)]
107pub mod error;
108#[cfg(windows)]
109pub mod instance;
110#[cfg(windows)]
111pub mod paths;
112#[cfg(windows)]
113pub mod shell;
114#[cfg(windows)]
115pub mod shortcuts;
116
117#[cfg(windows)]
118pub use error::{Error, Result};
119
120#[cfg(windows)]
121pub use elevation::{is_elevated, restart_as_admin, run_as_admin, run_with_verb};
122#[cfg(windows)]
123pub use instance::{
124 single_instance, single_instance_with_options, single_instance_with_scope, InstanceGuard,
125 InstanceScope, SingleInstanceOptions,
126};
127#[cfg(windows)]
128pub use paths::{ensure_local_app_data, ensure_roaming_app_data, local_app_data, roaming_app_data};
129#[cfg(windows)]
130pub use shell::{
131 empty_recycle_bin, empty_recycle_bin_for_root, move_paths_to_recycle_bin, move_to_recycle_bin,
132 open_containing_folder, open_url, open_with_default, open_with_verb, print_with_default,
133 reveal_in_explorer, show_properties,
134};
135#[cfg(windows)]
136pub use shortcuts::{create_shortcut, create_url_shortcut, ShortcutIcon, ShortcutOptions};