C++如何读取和修改可执行文件的图标资源

来源:Java编程网作者:广州GEO公司头衔:草根站长
导读:本期聚焦于小伙伴创作的《C++如何读取和修改可执行文件的图标资源》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《C++如何读取和修改可执行文件的图标资源》有用,将其分享出去将是对创作者最好的鼓励。

在Windows平台下,可执行文件的图标资源存储在PE格式文件的资源段中,我们可以通过Win32提供的资源操作API直接对这部分资源进行读取和修改,不需要借助额外的第三方工具。这种方式适合需要在程序运行时动态调整自身或目标程序图标的场景,比如多皮肤程序、自定义安装包生成工具等。

C++如何读取和修改可执行文件的图标资源

核心Win32资源API介绍

实现图标资源的读取和修改,主要依赖以下几个核心API:

  • FindResource:用于在指定模块的指定资源类型中查找目标资源,返回资源句柄。
  • LoadResource:根据资源句柄加载资源到内存,返回资源数据句柄。
  • LockResource:锁定加载到内存的资源,返回指向资源数据的指针。
  • BeginUpdateResource:打开可执行文件用于资源更新,返回更新句柄。
  • UpdateResource:向目标可执行文件写入新的资源数据。
  • EndUpdateResource:结束资源更新操作,提交修改到文件。

读取可执行文件图标资源的实现

读取图标资源的核心思路是先定位到目标可执行文件中的图标资源,再加载并解析资源数据。以下是完整的实现代码:

#include <windows.h>
#include <iostream>

// 读取目标可执行文件的第一个图标资源
bool ReadExeIcon(const wchar_t* exePath) {
    // 加载目标可执行文件作为模块,不执行其中的代码
    HMODULE hModule = LoadLibraryEx(exePath, NULL, LOAD_LIBRARY_AS_DATAFILE);
    if (hModule == NULL) {
        std::wcout << L"加载可执行文件失败,错误码:" << GetLastError() << std::endl;
        return false;
    }

    // 查找图标资源,RT_ICON是系统预定义的图标资源类型,这里查找第一个图标
    HRSRC hRes = FindResource(hModule, MAKEINTRESOURCE(1), RT_ICON);
    if (hRes == NULL) {
        std::wcout << L"未找到图标资源,错误码:" << GetLastError() << std::endl;
        FreeLibrary(hModule);
        return false;
    }

    // 获取资源大小
    DWORD resSize = SizeofResource(hModule, hRes);
    if (resSize == 0) {
        std::wcout << L"获取资源大小失败,错误码:" << GetLastError() << std::endl;
        FreeLibrary(hModule);
        return false;
    }

    // 加载资源到内存
    HGLOBAL hResData = LoadResource(hModule, hRes);
    if (hResData == NULL) {
        std::wcout << L"加载资源失败,错误码:" << GetLastError() << std::endl;
        FreeLibrary(hModule);
        return false;
    }

    // 锁定资源获取指针
    LPVOID pResData = LockResource(hResData);
    if (pResData == NULL) {
        std::wcout << L"锁定资源失败,错误码:" << GetLastError() << std::endl;
        FreeLibrary(hModule);
        return false;
    }

    std::wcout << L"成功读取图标资源,资源大小:" << resSize << L" 字节" << std::endl;
    // 这里可以对pResData指向的图标数据做进一步处理,比如保存为ico文件

    // 释放资源
    FreeLibrary(hModule);
    return true;
}

int main() {
    // 替换为目标可执行文件路径
    const wchar_t* targetExe = L"C:\Windows\notepad.exe";
    ReadExeIcon(targetExe);
    return 0;
}

修改可执行文件图标资源的实现

修改图标资源需要使用资源更新相关的API,需要注意的是目标可执行文件不能有只读属性,且最好先备份原文件避免操作失败导致文件损坏。以下是修改图标资源的完整代码:

#include <windows.h>
#include <iostream>

// 修改目标可执行文件的第一个图标资源
bool ModifyExeIcon(const wchar_t* targetExePath, const wchar_t* newIconPath) {
    // 加载新的图标文件
    HICON hNewIcon = (HICON)LoadImage(NULL, newIconPath, IMAGE_ICON, 0, 0, LR_LOADFROMFILE);
    if (hNewIcon == NULL) {
        std::wcout << L"加载新图标文件失败,错误码:" << GetLastError() << std::endl;
        return false;
    }

    // 获取图标数据大小
    DWORD iconSize = 0;
    // 先获取需要的缓冲区大小
    GetIconInfo(hNewIcon, NULL);
    // 这里简化操作,直接使用系统API获取图标资源数据,实际场景中可以先将图标转换为符合PE资源格式的二进制数据
    // 打开目标可执行文件用于资源更新
    HANDLE hUpdate = BeginUpdateResource(targetExePath, FALSE);
    if (hUpdate == NULL) {
        std::wcout << L"打开可执行文件更新失败,错误码:" << GetLastError() << std::endl;
        DestroyIcon(hNewIcon);
        return false;
    }

    // 将图标转换为资源数据,这里使用简化的方式,实际需要将图标转换为RT_ICON格式的二进制数据
    // 以下示例假设已经获取到正确的图标资源数据,实际开发中可以通过序列化图标结构得到
    // 这里仅演示API调用流程,真实场景需要处理图标数据的格式转换
    BYTE dummyData[1] = {0}; // 实际替换为真实的图标资源数据
    if (!UpdateResource(hUpdate, RT_ICON, MAKEINTRESOURCE(1), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), dummyData, sizeof(dummyData))) {
        std::wcout << L"更新资源失败,错误码:" << GetLastError() << std::endl;
        EndUpdateResource(hUpdate, TRUE); // 回滚修改
        DestroyIcon(hNewIcon);
        return false;
    }

    // 提交资源修改
    if (!EndUpdateResource(hUpdate, FALSE)) {
        std::wcout << L"提交资源修改失败,错误码:" << GetLastError() << std::endl;
        DestroyIcon(hNewIcon);
        return false;
    }

    std::wcout << L"成功修改可执行文件图标资源" << std::endl;
    DestroyIcon(hNewIcon);
    return true;
}

int main() {
    // 替换为目标可执行文件路径和新图标路径
    const wchar_t* targetExe = L"C:\test\target.exe";
    const wchar_t* newIcon = L"C:\test\new.ico";
    ModifyExeIcon(targetExe, newIcon);
    return 0;
}

注意事项

  • 修改可执行文件资源时,目标文件不能被其他进程占用,否则更新操作会失败。
  • 图标资源有多个尺寸和色深版本,如果需要完整替换所有图标变体,需要遍历所有图标资源ID进行更新。
  • 操作前建议备份目标可执行文件,避免资源格式错误导致文件无法运行。
  • 如果是修改当前正在运行的程序自身的图标,需要先复制到临时文件再操作,因为正在运行的程序文件会被系统锁定。

Win32_API可执行文件图标修改资源操作C_plus_plus修改时间:2026-06-19 07:48:37

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。