wininskit 0.1.2

Thin checked wrappers over the Win32 an installer needs: elevation, ACLs, services, the Restart Manager, the registry and shortcuts.
//! Asks the Restart Manager who is holding a folder, which is a different
//! question from who is holding a file and may not have the same answer.
//!
//! `cargo run -p wininskit --example holders [path]`
//!
//! With no path it makes a folder, has another process sit in it the way an
//! Explorer window does, and reports what comes back.

use std::{path::PathBuf, process::Command};

fn main() {
    let mut arguments = std::env::args().skip(1);
    if let Some(path) = arguments.next() {
        report(&PathBuf::from(path));
        return;
    }

    let folder = std::env::temp_dir().join("wininskit-holders");
    let _ = std::fs::remove_dir_all(&folder);
    std::fs::create_dir_all(&folder).expect("create the folder");
    std::fs::write(folder.join("a.bin"), b"x").expect("write a file");

    println!("nothing holding it yet:");
    report(&folder);

    let mut holder = Command::new("cmd")
        .args(["/c", "pause"])
        .current_dir(&folder)
        .stdin(std::process::Stdio::piped())
        .stdout(std::process::Stdio::piped())
        .spawn()
        .expect("start the holder");
    {
        use std::io::Read;
        let mut byte = [0u8; 1];
        let _ = holder.stdout.as_mut().expect("piped").read(&mut byte);
    }
    println!("\nwith pid {} sitting in it:", holder.id());
    report(&folder);

    // And the file inside it, for comparison: a file is what the Restart
    // Manager is built to answer about.
    println!("\nthe file inside it:");
    report(&folder.join("a.bin"));

    println!("\ncan the folder be removed?");
    let _ = std::fs::remove_file(folder.join("a.bin"));
    match std::fs::remove_dir(&folder) {
        Ok(()) => println!("  yes"),
        Err(error) => println!("  no: {error}"),
    }

    let _ = holder.kill();
    let _ = holder.wait();
    let _ = std::fs::remove_dir_all(&folder);
}

fn report(path: &std::path::Path) {
    match wininskit::locking_processes(&[path]) {
        Ok(found) if found.is_empty() => println!("  nothing reported"),
        Ok(found) => {
            for process in &found {
                println!("  pid {} {}", process.id, process.name);
            }
        }
        Err(error) => println!("  failed: {error}"),
    }
}