Add tree view

This commit is contained in:
aNNiMON 2024-07-24 00:00:35 +03:00
parent c46b6899b8
commit 63c21f929f
2 changed files with 49 additions and 4 deletions

View File

@ -1,5 +1,6 @@
use itertools::Itertools; use itertools::Itertools;
use processes::terminate_process; use processes::{terminate_process, ProcessInfo};
use std::collections::HashMap;
use std::process::ExitCode; use std::process::ExitCode;
use std::{env, fmt::Display}; use std::{env, fmt::Display};
@ -9,6 +10,7 @@ mod processes;
enum Mode { enum Mode {
Minimal, Minimal,
All, All,
Tree,
Filtered(String), Filtered(String),
Single(String), Single(String),
TerminateByPid(u32), TerminateByPid(u32),
@ -27,6 +29,10 @@ fn main() -> ExitCode {
show_processes_table(processes::list_processes()); show_processes_table(processes::list_processes());
ExitCode::SUCCESS ExitCode::SUCCESS
} }
Mode::Tree => {
show_processes_tree();
ExitCode::SUCCESS
}
Mode::Minimal => { Mode::Minimal => {
let filterlist = [ let filterlist = [
"svchost", "svchost",
@ -94,6 +100,7 @@ fn main() -> ExitCode {
"pkill => all unique processed, excl. system\n", "pkill => all unique processed, excl. system\n",
"pkill <name> => filtered processes by name or it's part\n", "pkill <name> => filtered processes by name or it's part\n",
"pkill -a/--all => all processes, incl. system\n", "pkill -a/--all => all processes, incl. system\n",
"pkill -t/--tree => all processes as tree\n",
"pkill -p/--pid <name> => PID of the first occurence\n", "pkill -p/--pid <name> => PID of the first occurence\n",
"pkill -k1/--kill <PID>/<name> => terminate process by its PID or name\n", "pkill -k1/--kill <PID>/<name> => terminate process by its PID or name\n",
"pkill -h/--help => print help\n", "pkill -h/--help => print help\n",
@ -110,9 +117,8 @@ fn parse_mode() -> Mode {
while let Some(el) = iter.next() { while let Some(el) = iter.next() {
match el.as_str() { match el.as_str() {
"-h" | "--help" => mode = Mode::Help, "-h" | "--help" => mode = Mode::Help,
"-a" | "--all" => { "-a" | "--all" => mode = Mode::All,
mode = Mode::All; "-t" | "--tree" => mode = Mode::Tree,
}
"-p" | "--pid" => { "-p" | "--pid" => {
if let Some(name) = iter.next() { if let Some(name) = iter.next() {
mode = Mode::Single(name.to_ascii_lowercase()); mode = Mode::Single(name.to_ascii_lowercase());
@ -139,6 +145,44 @@ fn parse_mode() -> Mode {
mode mode
} }
fn show_processes_tree() {
let processes: Vec<ProcessInfo> = processes::list_processes()
.into_iter()
.sorted_by_key(|p| p.parent_pid)
.collect();
let by_pid: HashMap<u32, ProcessInfo> =
processes.clone().into_iter().map(|p| (p.pid, p)).collect();
let mut tree: HashMap<u32, Vec<ProcessInfo>> = HashMap::new();
let mut roots: Vec<ProcessInfo> = 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<u32, Vec<ProcessInfo>>, 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<T>(items: T) fn show_processes_table<T>(items: T)
where where
T: IntoIterator, T: IntoIterator,

View File

@ -11,6 +11,7 @@ use windows::Win32::{
}, },
}; };
#[derive(Clone)]
pub struct ProcessInfo { pub struct ProcessInfo {
pub pid: u32, pub pid: u32,
pub parent_pid: u32, pub parent_pid: u32,