win-desktop-utils
Windows desktop helpers for Rust apps that need the Windows shell without owning raw Win32 glue.
win-desktop-utils wraps Windows-specific tasks that show up in desktop apps:
shell opening, Explorer reveal, Recycle Bin moves, shortcuts, app-data paths,
single-instance locks, and elevation prompts. Use the low-level helpers
directly, or start with DesktopApp for the common "app identity,
app-data directory, and single-instance guard" workflow.
Suitable for:
- Rust GUI, tray, launcher, installer-adjacent, and local utility apps on Windows
- apps that want focused feature flags instead of a large desktop abstraction
- cross-platform apps that want Windows helpers to type-check behind shared code
Out of scope:
- window creation, widgets, rendering, menus, installers, services, or updates
- broad Win32 coverage; use the
windowscrate directly for that
Scope
This crate currently provides helpers to:
- open an existing file or directory with the default Windows handler
- open an existing file or directory with an explicit Windows shell verb
- open a URL with the default browser or registered handler
- reveal an existing path in Explorer
- move an existing file or directory to the Recycle Bin
- empty the Recycle Bin silently
- create Windows
.lnkshortcuts - create Internet Shortcut
.urlfiles - enforce single-instance behavior with a named mutex
- configure single-instance behavior with builder-style options
- resolve per-user roaming and local app-data paths
- create per-user roaming and local app-data paths if needed
- check whether the current process is elevated
- relaunch the current executable as administrator
- launch arbitrary commands through shell verbs such as
openorrunas
This crate is Windows-first. On non-Windows targets, the public API still
compiles and operational helpers return Error::Unsupported.
Installation
[]
= "0.5"
Default features enable the full API. To keep a dependency focused, disable defaults and opt into only the modules you need:
[]
= { = "0.5", = false, = ["paths", "instance"] }
For crates that only need these helpers in Windows-specific code, use a target-specific dependency:
[]
= "0.5"
For cross-platform crates that want the same public symbols available everywhere,
use a normal dependency and handle Error::Unsupported on non-Windows targets.
Quick Start
Why Use It
- Small API for Windows desktop tasks that otherwise require direct shell, COM, mutex, known-folder, or elevation calls.
- Validates inputs before crossing into shell, COM, known-folder, mutex, and elevation APIs where practical.
- No background runtime, async executor, telemetry, or global worker.
- Feature flags let apps opt into only the helper groups they use.
- Windows CI checks tests, clippy, examples, docs, package creation, dependency policy, public API semver, and feature combinations.
- Non-Windows CI checks that public stubs compile and return
Error::Unsupported.
Pick The Right Helper
| Need | Start with | Feature | Notes |
|---|---|---|---|
| App identity, app-data paths, and one-instance startup | DesktopApp |
app |
Keeps startup setup together |
| Per-user config, cache, logs, or state folders | ensure_local_app_data / ensure_roaming_app_data |
paths |
Creates folders only when using ensure_* |
| Current-session or global single-instance behavior | single_instance / SingleInstanceOptions |
instance |
Keep the guard alive |
| Open files, URLs, folders, Properties, or print verbs | open_with_default, open_url, open_with_verb |
shell |
Uses user shell associations |
| Show a file or folder in Explorer | reveal_in_explorer |
shell |
Starts explorer.exe |
| Move files or folders to the Recycle Bin | move_to_recycle_bin / move_paths_to_recycle_bin |
recycle-bin |
Requires absolute existing paths without NUL bytes |
Create .lnk or .url shortcuts |
create_shortcut / create_url_shortcut |
shortcuts |
Output parent must already be a directory |
| Check or request administrator elevation | is_elevated, restart_as_admin, run_as_admin |
elevation |
May show UAC and starts another process |
Feature Flags
app:DesktopAppfacade for app-data and single-instance startup.paths: per-user local and roaming app-data helpers.instance: named-mutex single-instance helpers.shell: shell opening, URL, Explorer, and shell-verb helpers.recycle-bin: Recycle Bin move and empty helpers.shortcuts:.lnkand.urlshortcut helpers.elevation: elevation detection and shell-based relaunch helpers.
Current API
DesktopAppopen_with_default(path)open_with_verb(verb, path)show_properties(path)print_with_default(path)open_url(url)reveal_in_explorer(path)open_containing_folder(path)move_to_recycle_bin(path)move_paths_to_recycle_bin(paths)empty_recycle_bin()empty_recycle_bin_for_root(root_path)create_shortcut(shortcut_path, target_path, options)create_url_shortcut(shortcut_path, url)single_instance(app_id)single_instance_with_scope(app_id, scope)single_instance_with_options(options)roaming_app_data(app_name)local_app_data(app_name)ensure_roaming_app_data(app_name)ensure_local_app_data(app_name)is_elevated()restart_as_admin(args)run_as_admin(executable, args)run_with_verb(verb, executable, args)InstanceScope::{CurrentSession, Global}SingleInstanceOptionsShortcutOptionsShortcutIcon
Cookbook
The docs/cookbook.md file has ready-to-adapt recipes for:
- starting a single-instance app
- creating local and roaming app-data folders
- opening files, URLs, folders, and Properties
- creating
.lnkand.urlshortcuts - relaunching as administrator
- moving files to the Recycle Bin
Additional guides:
docs/adoption.md: integration notes for common app layoutsdocs/feature-flags.md: minimal dependency snippets by featuredocs/integrations.md: framework and packaging integration sketchesdocs/overhead.md: runtime model, side costs, and dependency surfacedocs/which-api.md: pick the right helper for a taskdocs/side-effects.md: user-visible behavior and safety notesdocs/compatibility.md: OS, Rust, feature, and non-Windows build policydocs/design.md: project scope and API acceptance rulesdocs/testing.md: test structure and expectationsdocs/trust.md: maintenance, compatibility, and release guarantees
Examples
The examples/ directory includes runnable samples for:
- app-data path lookup and creation
- URL opening and Explorer reveal helpers
- shell verb execution for files and directories
- Recycle Bin integration
- shortcut creation
- elevation checks and relaunch
- launching arbitrary commands through shell verbs
- single-instance enforcement
- single-instance enforcement across all sessions
- builder-style single-instance options
- cohesive
DesktopAppstartup flow
See examples/README.md for expected behavior, side effects, and feature flags for each example.
A companion demo app repo is available at
funwithcthulhu/win-desktop-utils-demo.
It shows DesktopApp, app-data setup, single-instance startup, shell opening,
Explorer reveal, elevation checks, and shortcut creation in one small binary.
Run any example with:
cargo run --example single_instance
Why Not Use windows Directly?
Use windows directly when you need broad Win32 coverage, custom flags, direct
COM object ownership, or APIs outside this crate's scope.
Use win-desktop-utils when you want a small, documented layer for common
desktop app tasks with validation, Rust-friendly builders, examples, and a
stable public API.
Alternatives And Scope
This crate is not a GUI framework, installer, updater, service framework, or cross-platform desktop abstraction. It works well alongside GUI frameworks and installer tools by handling a small set of Windows desktop tasks that application code often needs after startup or in response to user actions.
Error behavior
The crate exposes a small public error type with explicit path-related cases.
Notable error distinctions include:
Error::InvalidInput(...)for empty or malformed inputError::PathNotAbsolutewhen an operation requires an absolute pathError::PathDoesNotExistwhen an operation requires an existing pathError::WindowsApi { .. }when a Win32 or shell operation reports failureError::Io(...)for underlying I/O failuresError::Unsupported(...)for Windows operations called on non-Windows targets
Behavior notes
open_with_defaultrequires a non-empty existing path without NUL bytes.open_with_verbrequires a non-empty existing path without NUL bytes and a non-empty shell verb such asopenorproperties.show_propertiesandprint_with_defaultare convenience wrappers over shell verbs.open_urltrims surrounding whitespace before delegating to the Windows shell.reveal_in_explorerrequires an existing path without NUL bytes and launchesexplorer.exe.open_containing_folderrequires an existing path without NUL bytes and opens its parent directory.move_to_recycle_binrequires an absolute existing path without NUL bytes and usesIFileOperationon a dedicated STA thread for recycle-bin behavior.move_paths_to_recycle_binvalidates every path before starting one recycle-bin shell operation.empty_recycle_binandempty_recycle_bin_for_rootpermanently empty Recycle Bin contents without showing shell UI.create_shortcutrequires an absolute.lnkpath, an existing output parent directory, and an existing absolute target path without NUL bytes.create_url_shortcutrequires an absolute.urlpath whose parent is an existing directory and rejects line breaks in URLs to avoid malformed shortcut files.roaming_app_dataandlocal_app_datareject empty, whitespace-only, or NUL-containing app names, then resolve the base directory viaSHGetKnownFolderPath.single_instanceuses aLocal\...named mutex, so the lock is scoped to the current Windows session.single_instance_with_scopecan opt into either the current-session (Local\...) or global (Global\...) namespace.SingleInstanceOptionsprovides a small builder around single-instance app ID and scope selection.single_instancerejects backslashes inapp_idbecause Windows reserves them for kernel-object namespaces such asLocal\andGlobal\.- Keep the returned
InstanceGuardalive for as long as the process should own the single-instance lock. restart_as_adminstarts a new elevated instance of the current executable and does not terminate the current process.run_as_adminstarts an arbitrary command with therunasshell verb and may trigger UAC.restart_as_admin,run_as_admin, andrun_with_verbreject arguments containing NUL bytes.- On non-Windows targets, public APIs compile and Windows operations return
Error::Unsupported.
Quality
The crate includes:
- automated tests for validation and single-instance behavior
- unit tests covering argument quoting and input normalization edge cases
- table-driven validation tests for quoting, identity, URL, verb, and path inputs
- doctest examples in the public modules
- rustdoc lint checks for public documentation quality
cargo xtaskautomation for docs, feature, package, and release checkscargo xtask release-auditchecks for release metadata and package contents- ignored manual Windows smoke tests available through
cargo xtask smoke - Windows CI via GitHub Actions for MSRV, formatting, tests, clippy, examples, doctests, docs, feature combinations, packaging, dependency policy, and semver checks
- non-Windows CI checks that the public API stubs compile and return unsupported errors
- scheduled CI to catch dependency, runner, and toolchain drift
- documentation link checks for local Markdown links
- docs published on docs.rs
The intended shape is a small API, documented behavior, predictable side effects, and no surprise runtime.
The minimum supported Rust version is 1.82, matching the current windows crate dependency floor.
Support Policy
- Supported OS family: Windows 10 and Windows 11.
- Non-Windows targets compile public API stubs that return
Error::Unsupported. - Supported Rust: 1.82 and newer.
- Public API compatibility is checked with
cargo-semver-checks. - Dependency advisories, licenses, duplicate versions, and sources are checked with
cargo-deny.
Links
- Crates.io: https://crates.io/crates/win-desktop-utils
- Docs: https://docs.rs/win-desktop-utils
- Repository: https://github.com/funwithcthulhu/win-desktop-utils
- Changelog: https://github.com/funwithcthulhu/win-desktop-utils/blob/main/CHANGELOG.md
- Cookbook: https://github.com/funwithcthulhu/win-desktop-utils/blob/main/docs/cookbook.md
- API guide: https://github.com/funwithcthulhu/win-desktop-utils/blob/main/docs/which-api.md
- Adoption notes: https://github.com/funwithcthulhu/win-desktop-utils/blob/main/docs/adoption.md
- Compatibility: https://github.com/funwithcthulhu/win-desktop-utils/blob/main/docs/compatibility.md
- Design contract: https://github.com/funwithcthulhu/win-desktop-utils/blob/main/docs/design.md
- Feature flags: https://github.com/funwithcthulhu/win-desktop-utils/blob/main/docs/feature-flags.md
- Integrations: https://github.com/funwithcthulhu/win-desktop-utils/blob/main/docs/integrations.md
- Demo app: https://github.com/funwithcthulhu/win-desktop-utils-demo
- Runtime overhead: https://github.com/funwithcthulhu/win-desktop-utils/blob/main/docs/overhead.md
- Testing guide: https://github.com/funwithcthulhu/win-desktop-utils/blob/main/docs/testing.md
- Maintenance policy: https://github.com/funwithcthulhu/win-desktop-utils/blob/main/docs/trust.md
- Roadmap: https://github.com/funwithcthulhu/win-desktop-utils/blob/main/ROADMAP.md