当前位置:   article > 正文

使用Python修改可执行文件-EXE的图标_改变exe文件图标 tkinter

改变exe文件图标 tkinter

这部分网上资料有点太少了…

在做Python 打包工具https://github.com/QPT-Family/QPT(将Python程序打包为EXE)项目的时候,有自定义EXE图标的需求,但QPT走的是SFX方案生成EXE,而且QPT是基于Python打造的,这就使得需要使用使用Python修改EXE的图标。

话不多说,俩方案,一个靠谱的,一个不靠谱的,先讲不靠谱的,因为不靠谱的很方便。

但在此之前,我们需要先准备仨材料:

  1. 生成的EXE
  2. Icon-A(EXE原始的Icon)
  3. Icon-B(需要被替换的Icon)

EXE可以用C++直接生成一个就好,源码可以是:

#include <iostream>
using namespace std;
int main(){
    cout << "Hello 老张" << endl;
    system("pause");
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

icon的话,可以去QPT项目下直接找https://github.com/QPT-Family/QPT ,放在了ext/rc目录下,有俩不像样的icon。

准备基础的文件后,我们还要先了解一些基础的知识~

1. 前置知识

用一句话概括,那就是修改PE(Portable Executable)信息来达到修改图标的目的。

当然,想深入了解PE的话,本文是不会写的,但不妨碍去网上搜索哈哈哈,这里只讲一下怎么修改图标。

首先,我们在构建EXE的时候,指定了一个Icon,这个Icon在生成EXE后会出现哪里呢?
如果你安装了7-zip这样的工具,不妨试试看是否当作压缩包来打开(实际上显示的是类PE结构),打开后如下图所示:
在这里插入图片描述
可以很清晰的看见各部位的偏移、以及其虚拟地址,包括资源大小也是能看到。
这时,我们再打开资源部分(.rsrc),找到ICON所在的资源位置,如下图所示:
在这里插入图片描述

解压后就会发现,这就是EXE的那个Icon!

好了,前置知识已经讲完了,接下来就先是不靠谱的操作了。

2. 方法1 不靠谱,但很方便的资源替换法

我们知道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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

这个方法之所以说不靠谱,是因为所有的资源文件,都有可能会被替换,例如程序中嵌入了一个ico,和应用程序的图标是一个icon,那么pe.replace(ic_b[22:], ic_b2[22:])会一视同仁。

最重要的是,还要考虑替换前后的图像信息长度。

那么接下来就是靠谱的方式了

3. 方法2 使用PeFile库修改图标

这里,非常建议先安装一个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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

4. 优化体验 接受jpg、png、bmp等格式的图片作为icon

这部分就得上很强大的pillow了,其实我们的问题不应该是如何让jpg、png、bmp嵌入EXE中,而是让它们变成ico格式就好,代码很简单:

    img = Image.open(img_path).resize((128, 128))
    img.save(ico_save_path, sizes=[(128, 128)])
  • 1
  • 2

参考链接

Python打包工具-QPT

在QPT中,对应的代码位置为:https://github.com/QPT-Family/QPT/blob/开发分支/qpt/kernel/qpe.py ,如有变动请自行在QPT中查找~

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/264848
推荐阅读
相关标签
  

闽ICP备14008679号