You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Windows系统中使用Rust获取任意文件或目录的ICO图标?

在Windows系统中用Rust获取文件/目录ICO图标的方法

方法一:调用Windows Shell API(微软官方windows crate)

用微软维护的windows crate直接对接Windows API,这是最原生可靠的方式,支持所有文件和目录的图标提取。

  1. 先在Cargo.toml里加依赖:
[dependencies]
windows = { version = "0.52", features = ["Win32_Shell_Shell32", "Win32_Gdi", "Win32_Foundation", "Win32_System_Com"] }
  1. 示例代码:
use windows::Win32::Shell::Shell32::{SHGetFileInfoW, SHGFI_ICON, SHGFI_LARGEICON, SHGFI_SMALLICON};
use windows::Win32::Foundation::{PWSTR, HICON};
use windows::Win32::Gdi::{DestroyIcon};
use std::ffi::OsStr;
use std::os::windows::ffi::OsStrExt;

// 获取文件/目录的图标句柄,large=true返回大图标,false返回小图标
fn get_file_icon(path: &str, large: bool) -> Option<HICON> {
    // 把路径转成Windows宽字符格式
    let wide_path: Vec<u16> = OsStr::new(path)
        .encode_wide()
        .chain(std::iter::once(0))
        .collect();
    
    let mut file_info = std::mem::zeroed();
    let flags = if large {
        SHGFI_ICON | SHGFI_LARGEICON
    } else {
        SHGFI_ICON | SHGFI_SMALLICON
    };

    unsafe {
        // 调用SHGetFileInfoW获取图标
        if SHGetFileInfoW(
            PWSTR(wide_path.as_ptr()),
            0,
            &mut file_info,
            std::mem::size_of_val(&file_info) as u32,
            flags
        ).is_null() {
            return None;
        }
        Some(file_info.hIcon)
    }
}

fn main() {
    // 示例:获取记事本的大图标
    let icon_handle = get_file_icon("C:\\Windows\\notepad.exe", true);
    
    if let Some(hicon) = icon_handle {
        // 这里可以对图标句柄做后续处理,比如转成ICO文件
        // 用完一定要销毁句柄,不然会内存泄漏
        unsafe { DestroyIcon(hicon); }
    }
}

如果要把图标句柄保存成ICO文件,可以搭配ico crate来处理数据转换,核心逻辑是把HICON里的位图数据提取出来再写入文件。

方法二:用封装好的第三方库ico_extract

不想写复杂的API调用?这个库已经把Windows API的逻辑封装好了,直接调用就能拿图标,适合快速开发。

  1. 加依赖:
[dependencies]
ico_extract = "0.2"
  1. 示例代码:
use ico_extract::IconExtractor;

fn main() {
    // 提取可执行文件的图标
    let exe_extractor = IconExtractor::new("C:\\Windows\\explorer.exe").unwrap();
    if let Some(main_icon) = exe_extractor.get_icon(0) {
        // 保存为ICO文件
        main_icon.save_to_file("explorer_icon.ico").unwrap();
    }

    // 提取目录的图标
    let dir_extractor = IconExtractor::new("C:\\Users").unwrap();
    if let Some(dir_icon) = dir_extractor.get_icon(0) {
        dir_icon.save_to_file("directory_icon.ico").unwrap();
    }
}

这个库会自动处理系统分配给目录或普通文件的图标,不用自己操心API细节,缺点是灵活性不如原生调用。

方法三:手动解析PE文件资源(仅适用于可执行文件)

如果只需要处理.exe、.dll这类PE格式文件,而且不想依赖Windows API,可以直接解析文件里的资源段提取图标。用goblin解析PE,ico处理图标格式:

  1. 加依赖:
[dependencies]
goblin = "0.7"
ico = "0.2"
  1. 示例代码:
use goblin::pe::PE;
use ico::IconDir;
use std::fs::File;
use std::io::Read;

fn extract_pe_icon(path: &str) -> Option<IconDir> {
    let mut file = File::open(path).ok()?;
    let mut buffer = Vec::new();
    file.read_to_end(&mut buffer).ok()?;

    // 解析PE文件结构
    let pe = PE::parse(&buffer).ok()?;
    if let Some(resources) = pe.resources {
        // 遍历资源表找ICON类型的资源
        for entry in resources.entries {
            if entry.name.to_string_lossy() == "ICON" {
                let icon_data = &buffer[entry.offset as usize..entry.offset as usize + entry.size as usize];
                return IconDir::read(icon_data).ok();
            }
        }
    }
    None
}

fn main() {
    if let Some(icon_dir) = extract_pe_icon("C:\\Windows\\notepad.exe") {
        let mut icon_file = File::create("notepad_icon.ico").unwrap();
        icon_dir.write(&mut icon_file).unwrap();
    }
}

注意:这个方法不能提取普通文件或目录的图标,因为这类图标是系统根据文件类型动态分配的,不在文件本身的资源里。

内容的提问来源于stack exchange,提问作者DLillard0

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 04:55:23