tasklist/infos/
mod.rs

1pub mod info;
2use std::collections::HashMap;
3use std::fmt;
4
5#[derive(Debug)]
6/// the process struct .
7/// ```
8/// use tasklist::Process;
9/// let p = Process::new(123,"yeah.exe".to_string());
10/// ```
11pub struct Process {
12    pub pid: u32,
13    pub pname: String,
14}
15impl Process {
16    ///new a process struct
17    /// ```
18    /// use tasklist::Process;
19    /// let p = Process::new(123,"yeah.exe".to_string());
20    /// ```
21    pub fn new(pid: u32, pname: String) -> Process {
22        Process {
23            pid: pid,
24            pname: pname,
25        }
26    }
27
28    ///get the process struct pid . return `u32`
29    pub fn get_pid(&self) -> u32 {
30        self.pid
31    }
32    ///get the process struct pname . return `String`
33    pub fn get_pname(&self) -> String {
34        self.pname.clone()
35    }
36    ///get the process SID . return `Result<String,String>`
37    pub fn get_sid(&self) -> Result<String,String> {
38        let pid = self.pid;
39        match get_proc_sid_and_user(pid) {
40            Ok((_, sid)) => return Ok(sid),
41            Err(err) => return Err(err),
42        };
43    }
44    ///get the process User . return `Result<String,String>`
45    pub fn get_user(&self) -> Result<String,String> {
46        let pid = self.pid;
47        match get_proc_sid_and_user(pid){
48            Ok((user, _)) => return Ok(user),
49            Err(err) => return Err(err),
50        };
51    }
52    ///get the process threadsID . return `Result<Vec<u32>,String>`
53    pub fn get_threads(&self) -> Result<Vec<u32>,String> {
54        match get_proc_threads(self.pid){
55            Ok(threads) => return Ok(threads),
56            Err(err) => return Err(err),
57        }
58    }
59    ///get the process path . return `Result<String, String>`
60    pub fn get_path(&self) -> Result<String, String> {
61        get_proc_path(self.pid)
62    }
63    ///get the process parrentID , return `Option<u32>`
64    pub fn get_parrent(&self) -> Option<u32> {
65        get_proc_parrent(self.pid)
66        
67    }
68    ///get the process start time . return `Result<String,String>`
69    pub fn get_start_time(&self) -> Result<String,String> {
70        match get_proc_time(self.pid){
71            Ok((start_time, _, _)) => return Ok(start_time),
72            Err(err) => return Err(err)
73        }
74    }
75    ///get process exit time . return `Result<String,String>`
76    pub fn get_exit_time(&self) -> Result<String,String> {
77        match get_proc_time(self.pid){
78            Ok((_, exit_time, _)) => return Ok(exit_time),
79            Err(err) => return Err(err)
80        }
81    }
82    ///get process cpu time infomation . return `Result<CpuTime,String>`
83    pub fn get_cpu_time(&self) -> Result<CpuTime,String> {
84        match get_proc_time(self.pid){
85            Ok((_, _, cpu_time)) => return Ok(cpu_time),
86            Err(err) => return Err(err)
87        }
88    }
89    ///get process commandline params . return `Result<String,String>`
90    pub fn get_cmd_params(&self) -> Result<String,String> {
91        get_proc_params(self.pid)
92    }
93
94    ///get process io counter . return a `IoCounter` struct
95    pub fn get_io_counter(&self) -> IoCounter {
96        get_proc_io_counter(self.pid)
97    }
98    ///get process memory counter . return a `MemoryCounter` struct
99    pub fn get_memory_info(&self) -> MemoryCounter {
100        get_proc_memory_info(self.pid)
101    }
102    ///get process handle counter
103    pub fn get_handles_counter(&self) -> Result<u32, String> {
104        match get_process_handle_counter(self.pid){
105            Ok(handle_count) => return Ok(handle_count),
106            Err(err) => return Err(err)
107        }
108    }
109    ///kill this process
110    pub fn kill(&self) -> Result<(), String> {
111        kill(self.pid)
112    }
113    /// get the file info of the process . use `GetFileVersionInfoExW` api . it will return a `HashMap<String,String>` including a lot of infomation.
114    /// you can get value throught `CompanyName` `FileDescription` `OriginalFilename` `ProductName` `ProductVersion` `PrivateBuild` `InternalName` `LegalCopyright` `FileVersion` keys.
115    pub fn get_file_info(&self) -> Result<HashMap<String, String>,String> {
116        get_proc_file_info(self.pid)
117    }
118     /// Check if process is running under WOW64
119    /// Returns None if failed to get information
120    pub fn is_wow64(&self) -> Option<bool> {
121        is_wow_64(self.pid)
122    }
123
124    /// Get process architecture information
125    /// Returns tuple: (is_wow64: bool, process_arch: &str, native_arch: &str)
126    /// Returns None if failed to get information
127    pub fn get_architecture_info(&self) -> Option<(bool, &'static str, &'static str)> {
128        unsafe { is_wow_64_2(self.pid) }
129    }
130        /// Get specific file info item by key
131    /// Returns None if key doesn't exist
132    pub fn get_file_info_item(&self, key: &str) -> Option<String> {
133        match self.get_file_info(){
134            Ok(map) => map.get(key).map(|s| s.to_string()),
135            Err(_) => None,
136        }
137    }
138
139    /// Get company name from file info
140    pub fn get_company_name(&self) -> Option<String> {
141        self.get_file_info_item("CompanyName")
142    }
143
144    /// Get file description from file info
145    pub fn get_file_description(&self) -> Option<String> {
146        self.get_file_info_item("FileDescription")
147    }
148    /// Check if process is still running
149    pub fn is_running(&self) -> bool {
150        get_proc_parrent(self.pid).is_some() 
151    }
152}
153
154impl fmt::Display for Process {
155    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
156        write!(f, "{} {}", self.pname, self.pid)
157    }
158}
159
160use crate::{get_proc_name, kill};
161use std::mem::{size_of, zeroed};
162use crate::{is_wow_64, is_wow_64_2};
163use windows::Win32::Foundation::{CloseHandle, HANDLE};
164use windows::Win32::System::Diagnostics::ToolHelp::{
165    CreateToolhelp32Snapshot, Process32FirstW, Process32NextW, PROCESSENTRY32W, TH32CS_SNAPPROCESS,
166};
167
168use self::info::{
169    get_proc_file_info, get_proc_io_counter, get_proc_memory_info, get_proc_params,
170    get_proc_parrent, get_proc_path, get_proc_sid_and_user, get_proc_threads, get_proc_time,
171    get_process_handle_counter,
172};
173///this struct is `Process` Iterator.
174pub struct Tasklist {
175    pub(crate) process: Process,
176    pub(crate) index: usize,
177    pub(crate) handle: HANDLE,
178    pub(crate) entry: PROCESSENTRY32W,
179}
180impl Tasklist {
181    pub fn new() -> Result<Tasklist, String> {
182        unsafe {
183            let h = match CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) {
184                Ok(handle) => handle,
185                Err(e) => return Err(format!("CreateToolhelp32Snapshot failed: {:?}", e)),
186            };
187    
188            let mut process = zeroed::<PROCESSENTRY32W>();
189            process.dwSize = size_of::<PROCESSENTRY32W>() as u32;
190    
191            match Process32FirstW(h, &mut process) {
192                Ok(_) => {
193                    let pid = process.th32ProcessID;
194                    let pname = get_proc_name(&process.szExeFile);
195                    Ok(Tasklist {
196                        process: Process::new(pid, pname),
197                        index: 0,
198                        handle: h,
199                        entry: process,
200                    })
201                },
202                Err(e) => Err(format!("Process32FirstW failed: {:?}", e))
203            }
204        }
205}
206}
207impl Drop for Tasklist {
208    fn drop(&mut self) {
209        unsafe {
210            let _ = CloseHandle(self.handle);
211        }
212    }
213}
214impl Iterator for Tasklist {
215    type Item = Process;
216
217    fn next(&mut self) -> Option<<Self as Iterator>::Item> {
218        self.index = self.index + 1;
219        if self.index == 1 {
220            return Some(Process::new(self.process.pid, self.process.pname.clone()));
221        }
222        let mut process = self.entry;
223
224        unsafe {
225            match Process32NextW(self.handle, &mut process){
226                 Ok(_)=>{
227                    let pid = process.th32ProcessID;
228                    let pname = get_proc_name(&process.szExeFile);
229                    Some(Process::new(pid, pname))
230                },
231                Err(_)=>{
232                    None
233                }
234              
235            }
236        }
237    }
238}
239impl fmt::Debug for Tasklist {
240    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
241        f.debug_struct("Tasklist")
242            .field("process", &self.process)
243            .field("index", &self.index)
244            .field("handle", &self.handle.0)
245            .field("entry", &format_args!("PROCESSENTRY32W"))
246            .finish()
247    }
248}
249
250use windows::Win32::System::ProcessStatus::PROCESS_MEMORY_COUNTERS;
251
252///process's memory counter struct . can easily get memory infomation of a process.
253pub struct MemoryCounter {
254    pub page_fault_count: u32,
255    pub peak_working_set_size: usize,
256    pub working_set_size: usize,
257    pub quota_peak_paged_pool_usage: usize,
258    pub quota_paged_pool_usage: usize,
259    pub quota_peak_non_paged_pool_usage: usize,
260    pub quota_non_paged_pool_usage: usize,
261    pub pagefile_usage: usize,
262    pub peak_pagefile_usage: usize,
263}
264impl MemoryCounter {
265    pub(crate) fn new(pmc: PROCESS_MEMORY_COUNTERS) -> MemoryCounter {
266        MemoryCounter {
267            page_fault_count: pmc.PageFaultCount,
268            peak_working_set_size: pmc.PeakWorkingSetSize,
269            working_set_size: pmc.WorkingSetSize,
270            quota_peak_paged_pool_usage: pmc.QuotaPeakPagedPoolUsage,
271            quota_paged_pool_usage: pmc.QuotaPagedPoolUsage,
272            quota_peak_non_paged_pool_usage: pmc.QuotaPeakNonPagedPoolUsage,
273            quota_non_paged_pool_usage: pmc.QuotaNonPagedPoolUsage,
274            pagefile_usage: pmc.PagefileUsage,
275            peak_pagefile_usage: pmc.PeakPagefileUsage,
276        }
277    }
278    ///get the process's page fault count
279    pub fn get_page_fault_count(&self) -> u32 {
280        self.page_fault_count
281    }
282
283    ///get the process's peak working set size
284    pub fn get_peak_working_set_size(&self) -> usize {
285        self.peak_working_set_size
286    }
287    pub fn get_working_set_size(&self) -> usize {
288        self.working_set_size
289    }
290    ///get the process's quota peak paged pool usage
291    pub fn get_quota_peak_paged_pool_usage(&self) -> usize {
292        self.quota_peak_paged_pool_usage
293    }
294    ///get the process's quota paged pool usage
295    pub fn get_quota_paged_pool_usage(&self) -> usize {
296        self.quota_paged_pool_usage
297    }
298    ///get the process's quota peak non paged pool usage
299    pub fn get_quota_peak_non_paged_pool_usage(&self) -> usize {
300        self.quota_peak_non_paged_pool_usage
301    }
302
303    ///get the process's quota non paged pool usage
304    pub fn get_quota_non_paged_pool_usage(&self) -> usize {
305        self.quota_non_paged_pool_usage
306    }
307
308    ///get the process's pagefile usage
309    pub fn get_pagefile_usage(&self) -> usize {
310        self.pagefile_usage
311    }
312    ///get the process's pagefile usage
313    pub fn get_peak_pagefile_usage(&self) -> usize {
314        self.peak_pagefile_usage
315    }
316    /// Get total memory usage (working set + pagefile)
317    pub fn get_total_memory_usage(&self) -> usize {
318        self.working_set_size + self.pagefile_usage
319    }
320}
321
322use windows::Win32::System::Threading::IO_COUNTERS;
323/// the process's IO counter struct
324pub struct IoCounter {
325    pub read_operation_count: u64,
326    pub write_operation_count: u64,
327    pub other_operation_count: u64,
328    pub read_transfer_count: u64,
329    pub write_transfer_count: u64,
330    pub other_transfer_count: u64,
331}
332
333impl IoCounter {
334    pub(crate) fn new(ic: IO_COUNTERS) -> IoCounter {
335        IoCounter {
336            read_operation_count: ic.ReadOperationCount,
337            write_operation_count: ic.WriteOperationCount,
338            other_operation_count: ic.OtherOperationCount,
339            read_transfer_count: ic.ReadTransferCount,
340            write_transfer_count: ic.WriteTransferCount,
341            other_transfer_count: ic.OtherTransferCount,
342        }
343    }
344    ///get the process's read operation count
345    pub fn get_read_operation_count(&self) -> u64 {
346        self.read_operation_count
347    }
348    ///get the process's write operation count
349    pub fn get_write_operation_count(&self) -> u64 {
350        self.write_operation_count
351    }
352    ///get the process's other operation count
353    pub fn get_other_operation_count(&self) -> u64 {
354        self.other_operation_count
355    }
356    ///get the process's read transfer count
357    pub fn get_read_transfer_count(&self) -> u64 {
358        self.read_transfer_count
359    }
360    ///get the process's write transfer count
361    pub fn get_write_transfer_count(&self) -> u64 {
362        self.write_transfer_count
363    }
364    ///get the process's other transfer
365    pub fn get_other_transfer_count(&self) -> u64 {
366        self.other_transfer_count
367    }
368    /// Get total IO operations count
369    pub fn get_total_operations(&self) -> u64 {
370        self.read_operation_count + self.write_operation_count + self.other_operation_count
371    }
372}
373
374/// the struct of process's CpuTime .
375pub struct CpuTime {
376    pub kernel_time: String,
377    pub user_time: String,
378}
379
380impl CpuTime {
381    pub(crate) fn new(time: (String, String)) -> CpuTime {
382        return CpuTime {
383            kernel_time: time.0,
384            user_time: time.1,
385        };
386    }
387    ///get kernel time of the process
388    pub fn get_kernel_time(&self) -> String {
389        self.kernel_time.clone()
390    }
391    ///get user time of the process
392    pub fn get_user_time(&self) -> String {
393        self.user_time.clone()
394    }
395    /// Get total CPU time (kernel + user)
396    /// Returns formatted string with combined time
397    pub fn get_total_cpu_time(&self) -> String {
398        format!("{} + {}", self.kernel_time, self.user_time)
399    }
400}
401use std::fmt::Debug;
402impl Debug for CpuTime {
403    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
404        write!(f, "Kernel Time: {}, User Time: {}", self.kernel_time, self.user_time)
405    }
406    
407}