diff --git a/src/main.rs b/src/main.rs index 0d5659b..a0c3f28 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ use itertools::Itertools; -use processes::terminate_process; +use processes::{terminate_process, ProcessInfo}; +use std::collections::HashMap; use std::process::ExitCode; use std::{env, fmt::Display}; @@ -9,6 +10,7 @@ mod processes; enum Mode { Minimal, All, + Tree, Filtered(String), Single(String), TerminateByPid(u32), @@ -27,6 +29,10 @@ fn main() -> ExitCode { show_processes_table(processes::list_processes()); ExitCode::SUCCESS } + Mode::Tree => { + show_processes_tree(); + ExitCode::SUCCESS + } Mode::Minimal => { let filterlist = [ "svchost", @@ -94,6 +100,7 @@ fn main() -> ExitCode { "pkill => all unique processed, excl. system\n", "pkill => filtered processes by name or it's part\n", "pkill -a/--all => all processes, incl. system\n", + "pkill -t/--tree => all processes as tree\n", "pkill -p/--pid => PID of the first occurence\n", "pkill -k1/--kill / => terminate process by its PID or name\n", "pkill -h/--help => print help\n", @@ -110,9 +117,8 @@ fn parse_mode() -> Mode { while let Some(el) = iter.next() { match el.as_str() { "-h" | "--help" => mode = Mode::Help, - "-a" | "--all" => { - mode = Mode::All; - } + "-a" | "--all" => mode = Mode::All, + "-t" | "--tree" => mode = Mode::Tree, "-p" | "--pid" => { if let Some(name) = iter.next() { mode = Mode::Single(name.to_ascii_lowercase()); @@ -139,6 +145,44 @@ fn parse_mode() -> Mode { mode } +fn show_processes_tree() { + let processes: Vec = processes::list_processes() + .into_iter() + .sorted_by_key(|p| p.parent_pid) + .collect(); + + let by_pid: HashMap = + processes.clone().into_iter().map(|p| (p.pid, p)).collect(); + let mut tree: HashMap> = HashMap::new(); + let mut roots: Vec = Vec::new(); + for p in processes { + if p.pid != p.parent_pid && by_pid.contains_key(&p.parent_pid) { + tree.entry(p.parent_pid).or_default().push(p); + } else { + roots.push(p); + } + } + + println!("{:60} {:10} {:8}", "Name", "PID", "Threads"); + for root in roots { + display_process_tree(root, &tree, 0); + } +} + +fn display_process_tree(p: ProcessInfo, tree: &HashMap>, depth: usize) { + println!( + "{:<60} {:<10} {:<8}", + " ".repeat(depth * 2) + p.name.as_str(), + p.pid, + p.threads_count + ); + if let Some(children) = tree.get(&p.pid) { + for child in children { + display_process_tree(child.clone(), tree, depth + 1); + } + } +} + fn show_processes_table(items: T) where T: IntoIterator, diff --git a/src/processes.rs b/src/processes.rs index b4cce6b..25ea1ea 100644 --- a/src/processes.rs +++ b/src/processes.rs @@ -11,6 +11,7 @@ use windows::Win32::{ }, }; +#[derive(Clone)] pub struct ProcessInfo { pub pid: u32, pub parent_pid: u32,