赞
踩
这部分网上资料有点太少了…
在做Python 打包工具https://github.com/QPT-Family/QPT(将Python程序打包为EXE)项目的时候,有自定义EXE图标的需求,但QPT走的是SFX方案生成EXE,而且QPT是基于Python打造的,这就使得需要使用使用Python修改EXE的图标。
话不多说,俩方案,一个靠谱的,一个不靠谱的,先讲不靠谱的,因为不靠谱的很方便。
但在此之前,我们需要先准备仨材料:
EXE可以用C++直接生成一个就好,源码可以是:
#include <iostream>
using namespace std;
int main(){
cout << "Hello 老张" << endl;
system("pause");
return 0;
}
icon的话,可以去QPT项目下直接找https://github.com/QPT-Family/QPT ,放在了ext/rc
目录下,有俩不像样的icon。
准备基础的文件后,我们还要先了解一些基础的知识~
用一句话概括,那就是修改PE(Portable Executable)信息来达到修改图标的目的。
当然,想深入了解PE的话,本文是不会写的,但不妨碍去网上搜索哈哈哈,这里只讲一下怎么修改图标。
首先,我们在构建EXE的时候,指定了一个Icon,这个Icon在生成EXE后会出现哪里呢?
如果你安装了7-zip这样的工具,不妨试试看是否当作压缩包来打开(实际上显示的是类PE结构),打开后如下图所示:
可以很清晰的看见各部位的偏移、以及其虚拟地址,包括资源大小也是能看到。
这时,我们再打开资源部分(.rsrc),找到ICON所在的资源位置,如下图所示:
解压后就会发现,这就是EXE的那个Icon!
好了,前置知识已经讲完了,接下来就先是不靠谱的操作了。
我们知道PE中是有1.ico
这个文件的,那么我们直接用open()
函数打开这个exe文件,直接替换掉这个icon不就可以了吗?
没错,就是这样,非常简单!
exe = r"exe文件" icon = r"tmp_icon.ico" icon2 = r"test_icon.ico" # 二进制方式读取exe with open(exe, "rb") as f: pe = f.read() # 读取我们生成EXE时候的那个icon文件 with open(icon, "rb") as f: ic_b = f.read() # 读取我们要替换的icon文件 with open(icon2, "rb") as f: ic_b2 = f.read() # 从22的位置开始替换 - 为什么是22?可以自行了解一下图像文件的格式 pe = pe.replace(ic_b[22:], ic_b2[22:]) # 写入硬盘 with open("text3.exe", "wb") as f: f.write(pe)
这个方法之所以说不靠谱,是因为所有的资源文件,都有可能会被替换,例如程序中嵌入了一个ico,和应用程序的图标是一个icon,那么pe.replace(ic_b[22:], ic_b2[22:])
会一视同仁。
最重要的是,还要考虑替换前后的图像信息长度。
那么接下来就是靠谱的方式了
这里,非常建议先安装一个ExeScope,因为方便我们查看地址信息,不想安装的话也没什么问题,用PeFile也能打印出结构。
那么我们就先使用ExeScope打开EXE,找到图标所在位置吧~
然后选择二进制查看
我们可以看到图标所在的地址起始是0001D6E8,在Python中我们可以表示为0x1D6E8,接下来我们就使用PeFile来修改吧~
pe = pefile.PE(exe)
# offset 可从ExeScope中获取
rva = pe.get_rva_from_offset(0x1D6E8)
pe.set_bytes_at_rva(rva, ic_b2[22:])
f = pe.write()
with open("text4.exe", 'wb') as final_f:
final_f.write(f)
这部分就得上很强大的pillow了,其实我们的问题不应该是如何让jpg、png、bmp嵌入EXE中,而是让它们变成ico格式就好,代码很简单:
img = Image.open(img_path).resize((128, 128))
img.save(ico_save_path, sizes=[(128, 128)])
在QPT中,对应的代码位置为:https://github.com/QPT-Family/QPT/blob/开发分支/qpt/kernel/qpe.py ,如有变动请自行在QPT中查找~
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。