最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Rust調(diào)用Windows API 如何獲取正在運(yùn)行的全部進(jìn)程信息

 更新時(shí)間:2024年11月18日 11:35:22   作者:beifengtz  
本文介紹了如何使用Rust調(diào)用WindowsAPI獲取正在運(yùn)行的全部進(jìn)程信息,通過引入winapi依賴并添加相應(yīng)的features,可以實(shí)現(xiàn)對(duì)不同API集的調(diào)用,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧

前言

WIndows API官方文檔 提供了C++的調(diào)用示例,最近想嘗試用Rust去實(shí)現(xiàn),本系列博客記錄一下實(shí)現(xiàn)過程。

依賴

Rust調(diào)用Windows API需要引入依賴winapi,在Cargo.toml中添加依賴

winapi = "0.3.9"

調(diào)用不同的API集就需要使用相應(yīng)的功能features,很好的一個(gè)判斷方式是你在微軟官方文檔中看到的是在哪個(gè)頭文件內(nèi),就添加哪個(gè)feature,例如本篇文章需要使用 tlhelp32.h processthreadsapi.h 那么就將這倆feature添加進(jìn)去

winapi = { version = "0.3.9", features = ["tlhelp32", "processthreadsapi"] }

實(shí)現(xiàn)

大致步驟

  • 創(chuàng)建進(jìn)程快照,拿到快照句柄
  • 遍歷快照中的進(jìn)程(以迭代器的方式實(shí)現(xiàn)),得到每個(gè)進(jìn)程的數(shù)據(jù)
  • 釋放快照句柄

創(chuàng)建快照句柄

創(chuàng)建進(jìn)程快照需要用到 CreateToolhelp32Snapshot 方法,它在 tlhelp32.h 頭文件中定義。

use winapi::um::tlhelp32::{CreateToolhelp32Snapshot, TH32CS_SNAPPROCESS};
use winapi::um::handleapi::INVALID_HANDLE_VALUE;
use winapi::um::errhandlingapi::GetLastError;
/// 保存進(jìn)程快照并返回進(jìn)程信息迭代器 `ProcessInformationIterator`
pub fn list() -> Result<ProcessInformationIterator, String> {
    let process_snapshot: HANDLE = unsafe { CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) };
    if process_snapshot == INVALID_HANDLE_VALUE || process_snapshot.is_null() {
        unsafe {
            return Err(format!("Cannot list processes, code: {}", GetLastError()));
        }
    }
    Ok(ProcessInformationIterator::new(process_snapshot))
}

代碼中的 ProcessInfomationIterator 是自定義的,為了結(jié)構(gòu)更清晰,這里使用迭代器模式來讀取。

如果保存進(jìn)程快照失敗,返回的句柄會(huì)是一個(gè)無效的值(這里用了兩個(gè)條件或的關(guān)系去判斷是否無效,其實(shí)任用其一都可以,他們都表示一個(gè)“空”內(nèi)存或“空”指針),使用 GetLastError 方法可以獲取錯(cuò)誤代碼,錯(cuò)誤代碼對(duì)應(yīng)含義見系統(tǒng)錯(cuò)誤代碼說明,也可以通過API解析成可讀文本,這個(gè)后面的文章再介紹,這里先用code簡(jiǎn)單表示一下。

實(shí)現(xiàn)迭代器

Rust中的迭代器模式實(shí)現(xiàn)方法這里就不多贅述,你只需要知道實(shí)現(xiàn)一個(gè)迭代器至少需要 一個(gè)迭代元素Item一個(gè)實(shí)現(xiàn)了Iterator特征的迭代器 就可以了。

迭代元素Item

let vec = vec![1, 2]
for item in vec {
	...
}

上面代碼的item就是迭代器中具體的元素,因?yàn)檫M(jìn)程信息有很多,這里就使用一個(gè)結(jié)構(gòu)體來存

use winapi::um::tlhelp32::PROCESSENTRY32;
pub struct ProcessInformation {
    inner: PROCESSENTRY32,
}

這里并沒有直接將進(jìn)程的數(shù)據(jù)解析之后再存入結(jié)構(gòu)體,而是直接將 PROCESSENTRY32 結(jié)構(gòu)體做一個(gè)包裝,這里是為了節(jié)省不必要的計(jì)算,從句柄中直接讀取出來的 PROCESSENTRY32 并不是所有信息都是Rust直接可讀的,在需要時(shí)才解析,并且通過getter方法讀取數(shù)據(jù)更方便以后拓展,下面是ProcessInformation的具體方法實(shí)現(xiàn)。

use winapi::um::processthreadsapi::{GetPriorityClass, OpenProcess};
use winapi::um::errhandlingapi::GetLastError;
use winapi::um::tlhelp32::PROCESSENTRY32;
use winapi::um::winnt::{HANDLE, PROCESS_ALL_ACCESS};
pub(crate) fn char_arr_to_string(chars: &[i8]) -> String {
    chars.into_iter().map(|&c| c as u8 as char).collect()
}
impl ProcessInformation {
    pub(crate) fn new(entry: PROCESSENTRY32) -> ProcessInformation {
        ProcessInformation {
            inner: entry
        }
    }
    /// 獲取進(jìn)程ID
    pub fn get_pid(&self) -> u32 {
        self.inner.th32ProcessID as u32
    }
    /// 獲取進(jìn)程名
    pub fn get_name(&self) -> String {
        char_arr_to_string(&self.inner.szExeFile)
    }
    /// 獲取父進(jìn)程ID
    pub fn get_parent_pid(&self) -> u32 {
        self.inner.th32ParentProcessID as u32
    }
    /// 獲取線程數(shù)量
    pub fn get_thread_count(&self) -> usize {
        self.inner.cntThreads as usize
    }
    /// 獲取基礎(chǔ)優(yōu)先權(quán)值
    pub fn get_priority_base(&self) -> i64 {
        self.inner.pcPriClassBase as i64
    }
    /// 獲取優(yōu)先權(quán)類別,如果調(diào)用進(jìn)程沒有指定權(quán)限可能會(huì)獲取失敗,失敗時(shí)返回 `None`
    pub fn get_priority_class(&self) -> Option<i32> {
        let mut priority_class = None;
        unsafe {
            let handle = OpenProcess(PROCESS_ALL_ACCESS, 0, self.inner.th32ProcessID);
            if !handle.is_null() {
                let class = GetPriorityClass(handle);
                CloseHandle(handle);
                priority_class = Some(class as i32);
            }
        }
        priority_class
    }
}

迭代器實(shí)現(xiàn)

迭代器中需要保存一些迭代遍歷的狀態(tài),因此除了前面保存的快照句柄之外還要存儲(chǔ)迭代的索引以及釋放句柄的狀態(tài),迭代器是不可逆的。

use winapi::um::winnt::HANDLE;
pub struct ProcessInformationIterator {
    process_snapshot: HANDLE,
    index: usize,
    finished: bool,
}
impl ProcessInformationIterator {
    pub(crate) fn new(process_snapshot: HANDLE) -> ProcessInformationIterator {
        ProcessInformationIterator {
            process_snapshot,
            index: 0,
            finished: false,
        }
    }
}

然后就是迭代器的具體實(shí)現(xiàn)

use winapi::um::winnt::HANDLE;
use winapi::um::tlhelp32::{Process32First, Process32Next, PROCESSENTRY32};
use winapi::um::handleapi::CloseHandle;
impl Iterator for ProcessInformationIterator {
    type Item = ProcessInformation;
    fn next(&mut self) -> Option<Self::Item> {
        if self.finished {
            return None;
        }
        self.index += 1;
        let mut entry: PROCESSENTRY32 = unsafe { std::mem::zeroed() };
        entry.dwSize = size_of::<PROCESSENTRY32>() as u32;
        //  讀取快照中的第一個(gè)進(jìn)程
        let res = unsafe {
            if self.index == 1 {
                Process32First(self.process_snapshot, &mut entry)
            } else {
                Process32Next(self.process_snapshot, &mut entry)
            }
        };
        if res == 0 {
            unsafe {
                CloseHandle(self.process_snapshot);
            }
            self.finished = true;
            return None;
        }
        Some(ProcessInformation::new(entry))
    }
}

上面的代碼有幾點(diǎn)需要說明一下:

  • entry在初始化時(shí)需要先到一個(gè)全0值的內(nèi)存空間,并不是分配為一個(gè)Rust引用空間,這里用 unsafe 方法 std::mem::zeroed()
  • 在讀取進(jìn)程Entry之前需要先指定內(nèi)存長(zhǎng)度,這里用 size_of::<PROCESSENTRY32>() 來獲取并賦值給 entry.dwSize
  • 遍歷時(shí)第一個(gè)元素需要調(diào)用 Process32First讀取,后續(xù)的使用 Process32Next 讀取
  • 遍歷完時(shí)記得關(guān)閉快照劇本 使用 CloseHandle 接口

特殊情況處理:如果用戶并沒有迭代完,上面的代碼實(shí)現(xiàn)可能會(huì)出現(xiàn)快照句柄未釋放的情況,所以還需要給迭代器實(shí)現(xiàn)一個(gè)Drop特征,在釋放迭代器時(shí)釋放快照句柄

impl Drop for ProcessInformationIterator {
    fn drop(&mut self) {
        if self.finished {
            return;
        }
        // 釋放快照句柄。
        unsafe {
            CloseHandle(self.process_snapshot);
        }
        self.finished = true;
    }
}

代碼匯總

我在寫的時(shí)候放在了自定義的utils::process::win包下面,具體引用路徑根據(jù)自己的情況調(diào)整

mod.rs文件

use crate::utils::process::win::process_information::ProcessInformationIterator;
use winapi::um::tlhelp32::{CreateToolhelp32Snapshot, TH32CS_SNAPPROCESS};
use winapi::um::errhandlingapi::GetLastError;
use winapi::um::handleapi::INVALID_HANDLE_VALUE;
use winapi::um::winnt::HANDLE;
pub mod process_information;
pub fn list() -> Result<ProcessInformationIterator, String> {
    let process_snapshot: HANDLE = unsafe { CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) };
    if process_snapshot == INVALID_HANDLE_VALUE || process_snapshot.is_null() {
        unsafe {
            return Err(format!("Cannot list processes, code: {}", GetLastError()));
        }
    }
    Ok(ProcessInformationIterator::new(process_snapshot))
}
pub(crate) fn char_arr_to_string(chars: &[i8]) -> String {
    chars.into_iter().map(|&c| c as u8 as char).collect()
}

process_information.rs文件

use crate::utils::process::win::char_arr_to_string;
use crate::utils::process::win::process_module::ProcessModuleIterator;
use winapi::um::errhandlingapi::GetLastError;
use winapi::um::handleapi::CloseHandle;
use winapi::um::processthreadsapi::{GetPriorityClass, OpenProcess};
use winapi::um::tlhelp32::{Process32First, Process32Next, PROCESSENTRY32};
use winapi::um::winnt::{HANDLE, PROCESS_ALL_ACCESS};
/// [PROCESSENTRY32](https://learn.microsoft.com/zh-cn/windows/win32/api/tlhelp32/ns-tlhelp32-processentry32) 的Rust包裝實(shí)現(xiàn)
pub struct ProcessInformation {
    inner: PROCESSENTRY32,
}
impl ProcessInformation {
    pub(crate) fn new(entry: PROCESSENTRY32) -> ProcessInformation {
        ProcessInformation {
            inner: entry
        }
    }
    /// 獲取進(jìn)程ID
    pub fn get_pid(&self) -> u32 {
        self.inner.th32ProcessID as u32
    }
    /// 獲取進(jìn)程名
    pub fn get_name(&self) -> String {
        char_arr_to_string(&self.inner.szExeFile)
    }
    /// 獲取父進(jìn)程ID
    pub fn get_parent_pid(&self) -> u32 {
        self.inner.th32ParentProcessID as u32
    }
    /// 獲取線程數(shù)量
    pub fn get_thread_count(&self) -> usize {
        self.inner.cntThreads as usize
    }
    /// 獲取基礎(chǔ)優(yōu)先權(quán)值
    pub fn get_priority_base(&self) -> i64 {
        self.inner.pcPriClassBase as i64
    }
    /// 獲取優(yōu)先權(quán)類別,如果調(diào)用進(jìn)程沒有指定權(quán)限可能會(huì)獲取失敗,失敗時(shí)返回 `None`
    pub fn get_priority_class(&self) -> Option<i32> {
        let mut priority_class = None;
        unsafe {
            let handle = OpenProcess(PROCESS_ALL_ACCESS, 0, self.inner.th32ProcessID);
            if !handle.is_null() {
                let class = GetPriorityClass(handle);
                CloseHandle(handle);
                priority_class = Some(class as i32);
            }
        }
        priority_class
    }
}
pub struct ProcessInformationIterator {
    process_snapshot: HANDLE,
    index: usize,
    finished: bool,
}
impl ProcessInformationIterator {
    pub(crate) fn new(process_snapshot: HANDLE) -> ProcessInformationIterator {
        ProcessInformationIterator {
            process_snapshot,
            index: 0,
            finished: false,
        }
    }
}
impl Drop for ProcessInformationIterator {
    fn drop(&mut self) {
        if self.finished {
            return;
        }
        // 釋放快照句柄。
        unsafe {
            CloseHandle(self.process_snapshot);
        }
        self.finished = true;
    }
}
impl Iterator for ProcessInformationIterator {
    type Item = ProcessInformation;
    fn next(&mut self) -> Option<Self::Item> {
        if self.finished {
            return None;
        }
        self.index += 1;
        let mut entry: PROCESSENTRY32 = unsafe { std::mem::zeroed() };
        entry.dwSize = size_of::<PROCESSENTRY32>() as u32;
        //  讀取快照中的第一個(gè)進(jìn)程
        let res = unsafe {
            if self.index == 1 {
                Process32First(self.process_snapshot, &mut entry)
            } else {
                Process32Next(self.process_snapshot, &mut entry)
            }
        };
        if res == 0 {
            unsafe {
                CloseHandle(self.process_snapshot);
            }
            self.finished = true;
            return None;
        }
        Some(ProcessInformation::new(entry))
    }
}

測(cè)試

測(cè)試代碼

#[test]
pub fn test_list() {
    println!("PID\tName\tParent PID\tThreads\tPriority Base\tPriority Class");
    let iter = list().unwrap();
    for process in iter {
        let pid = process.get_pid();
        let name = process.get_name();
        let parent_pid = process.get_parent_pid();
        let thread_count = process.get_thread_count();
        let priority_base = process.get_priority_base();
        let priority_class = process.get_priority_class();
        println!("{}\t{}\t{}\t{}\t{}\t{:?}", pid, name, parent_pid, thread_count, priority_base, priority_class)
    }
}

結(jié)果

PID     Name    Parent PID      Threads Priority Base   Priority Class
0       [System Process]        0       6       0       None
4       System  0       236     8       None
64      Secure System   4       0       8       None
132     Registry        4       4       8       None
504     smss.exe        4       2       11      None
728     csrss.exe       712     11      13      None
824     wininit.exe     712     1       13      None
832     csrss.exe       816     15      13      None
...
12624   chrome.exe      12148   19      8       Some(32)
16352   chrome.exe      12148   18      4       Some(64)
14904   chrome.exe      12148   17      4       Some(64)
14672   wslinstaller.exe        892     2       8       None
11160   chrome.exe      12148   20      4       Some(64)
18048   chrome.exe      12148   19      4       Some(64)
5452    chrome.exe      12148   14      4       Some(64)
14468   svchost.exe     892     3       8       None
18060   chrome.exe      12148   14      4       Some(64)
17748   dllhost.exe     688     8       8       Some(32)
16084   vctip.exe       16648   27      8       Some(32)
9008    OpenConsole.exe 10644   6       8       Some(32)
15516   cargo.exe       10644   4       8       Some(32)
11312   cargo.exe       15516   4       8       Some(32)

到此這篇關(guān)于Rust調(diào)用Windows API 獲取正在運(yùn)行的全部進(jìn)程信息的文章就介紹到這了,更多相關(guān)Rust調(diào)用Windows API 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Rust語言之Copy和Clone詳解

    Rust語言之Copy和Clone詳解

    在 Rust 中,Copy 和 Clone trait 用于控制類型的復(fù)制行為。它們?cè)试S你定義如何復(fù)制類型的值,以及在什么情況下可以復(fù)制。本文將詳細(xì)介紹這兩個(gè) trait 的作用和用法,并通過代碼示例來展示它們的使用,需要的朋友可以參考下
    2023-05-05
  • rust的package,crate,module示例解析

    rust的package,crate,module示例解析

    rust提供了非常優(yōu)秀的包管理器cargo,我們可以使用crate,module,package來組織代碼,這篇文章主要介紹了rust的package,crate,module相關(guān)知識(shí),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-04-04
  • 使用vscode配置Rust運(yùn)行環(huán)境全過程

    使用vscode配置Rust運(yùn)行環(huán)境全過程

    VS Code對(duì)Rust有著較完備的支持,這篇文章主要給大家介紹了關(guān)于使用vscode配置Rust運(yùn)行環(huán)境的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2023-06-06
  • rust中的match表達(dá)式使用詳解

    rust中的match表達(dá)式使用詳解

    在rust中提供了一個(gè)極為強(qiáng)大的控制流運(yùn)算符match,這篇文章主要介紹了rust中的match表達(dá)式,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-08-08
  • Rust語言從入門到精通之Tokio的Channel深入理解

    Rust語言從入門到精通之Tokio的Channel深入理解

    這篇文章主要為大家介紹了Rust語言從入門到精通之Tokio的Channel深入理解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05
  • 前端基于Rust實(shí)現(xiàn)的Wasm進(jìn)行圖片壓縮的技術(shù)文檔(實(shí)現(xiàn)方案)

    前端基于Rust實(shí)現(xiàn)的Wasm進(jìn)行圖片壓縮的技術(shù)文檔(實(shí)現(xiàn)方案)

    在現(xiàn)代Web開發(fā)中,利用Rust編寫的圖片壓縮代碼可以編譯成WebAssembly(Wasm)模塊,Rust的內(nèi)存安全特性和Wasm的跨平臺(tái)能力,使得這種方案既高效又安全,對(duì)Rust?Wasm圖片壓縮實(shí)現(xiàn)方案感興趣的朋友一起看看吧
    2024-09-09
  • Rust 中的閉包之捕獲環(huán)境的匿名函數(shù)

    Rust 中的閉包之捕獲環(huán)境的匿名函數(shù)

    這篇文章介紹了Rust編程語言中的閉包,包括閉包的定義、使用、捕獲環(huán)境中的變量、類型推斷與注解、與函數(shù)的比較以及實(shí)際應(yīng)用,閉包具有捕獲環(huán)境、類型推斷和高效性等特性,是Rust中一個(gè)非常強(qiáng)大的工具,感興趣的朋友一起看看吧
    2025-02-02
  • 一文帶你了解Rust是如何處理錯(cuò)誤的

    一文帶你了解Rust是如何處理錯(cuò)誤的

    程序在運(yùn)行的過程中,總是會(huì)不可避免地產(chǎn)生錯(cuò)誤,而如何優(yōu)雅地解決錯(cuò)誤,也是語言的設(shè)計(jì)哲學(xué)之一。本文就來和大家來了Rust是如何處理錯(cuò)誤的,感興趣的可以了解一下
    2022-11-11
  • 詳解thiserror庫在Rust中的使用

    詳解thiserror庫在Rust中的使用

    在編程中,錯(cuò)誤處理是一個(gè)至關(guān)重要的部分,在Rust中,我們經(jīng)常使用Result和Option類型來進(jìn)行錯(cuò)誤處理,但有時(shí),我們需要?jiǎng)?chuàng)建自定義的錯(cuò)誤類型,這就是thiserror庫發(fā)揮作用的地方,可以極大的簡(jiǎn)化代碼,所以本文就給大家介紹一下如何使用thiserror
    2023-08-08
  • 為什么要使用 Rust 語言、Rust 語言有什么優(yōu)勢(shì)

    為什么要使用 Rust 語言、Rust 語言有什么優(yōu)勢(shì)

    雖然 Rust 是一種通用的多范式語言,但它的目標(biāo)是 C 和 C++占主導(dǎo)地位的系統(tǒng)編程領(lǐng)域,很多朋友會(huì)問rust語言難學(xué)嗎?rust語言可以做什么,今天帶著這些疑問通過本文詳細(xì)介紹下,感興趣的朋友一起看看吧
    2022-10-10

最新評(píng)論

洛隆县| 遂川县| 建始县| 罗甸县| 锡林浩特市| 邵东县| 白城市| 上饶市| 鲁山县| 玉林市| 兴隆县| 古浪县| 曲麻莱县| 海林市| 祥云县| 栾川县| 资源县| 眉山市| 德令哈市| 中山市| 三门峡市| 临海市| 遵义市| 双桥区| 沭阳县| 青神县| 含山县| 大田县| 滨州市| 油尖旺区| 息烽县| 中超| 边坝县| 中方县| 宁阳县| 蕲春县| 屏边| 四会市| 中西区| 黄梅县| 巴林左旗|