<p>我做了一些研究,也贴出来了。如果你想看到结果代码(我希望它正是你所要求的),你可以在下面的“水平规则”之后找到它。在</p>
<p>首先,我尝试使用下一个代码来确定文件资源中存储的图标大小:</p>
<pre><code># Using LoadLibrary (rather than CreateFile) is required otherwise
# LoadResource, FindResource and others will fail
PATH = ... # Valid file path
hlib = win32api.LoadLibrary(PATH)
# This loop should print sizes of resources icons
icon_names = win32api.EnumResourceNames(hlib, win32con.RT_ICON)
for icon_name in icon_names:
rec = win32api.LoadResource(hlib, win32con.RT_ICON, icon_name)
hicon = win32gui.CreateIconFromResource(rec, True)
info = win32gui.GetIconInfo(hicon)
bminfo = win32gui.GetObject(info[3])
print("%2d: 0x%08X -> %d %d " % (icon_name, hicon, bminfo.bmWidth, bminfo.bmHeight))
</code></pre>
<p>虽然文件只包含16x16和32x32像素的图标,但一切都会正常,下面是Windows XP calculator的输出:</p>
^{pr2}$
<p>一旦我尝试了使用大图标的文件,我得到了一个例外:</p>
<pre><code>Traceback (most recent call last):
File "extract_icon.py", line 50, in <module>
hicon = win32gui.CreateIconFromResource(rec, True)
pywintypes.error: (0, 'CreateIconFromResource', 'No error message is available')
</code></pre>
<p>经过一些研究,我发现<strong>大图标不是以<code>ico</code></strong>格式存储的,而是以<code>png</code>格式存储的(对于我的例子)。在</p>
<p>当然,我不知道你的<code>.exe</code>文件到底是什么(它的内部结构),但是在我分析了我在我的电脑里找到的几个<code>.exe</code>文件后,我发现大于32x32或16x16像素的图标最有可能是通过<code>.png</code>文件来表示的(你可以使用<a href="http://www.heaventools.ru/">PE Explorer</a>,试用版已经存在)。在</p>
< >从资源中读取图像,我使用了C++上的<a href="http://www.codeproject.com/Articles/17996/Load-JPEG-images-from-DLL-with-LoadResource-in-Man">guide</a>。这里的主要目标是获取指向图像资源真实数据的指针,并将其复制到Python缓冲区。最后一步是把它保存到文件中(我想你可以自己把它翻译成PIL)。在</p>
<hr/>
<p><strong>完成读取大量资源的代码</strong>:</p>
<pre><code># Use wchar_t function version (FindResourceW rather than FindResourceA)
from __future__ import unicode_literals
# pywin32 imports
import pywintypes
import win32ui
import win32gui
import win32con
import win32api
import win32file
# ctypes configuring. pywin32 has no a lot of required functions
import ctypes
import ctypes.util
# memcpy used to copy data from resource storage to our buffer
libc = ctypes.CDLL(ctypes.util.find_library('c'))
libc.memcpy.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_size_t]
libc.memcpy.restype = ctypes.c_char_p
# All Windows backslashes must be escaped to LoadLibrary worked correctly '\' -> '\\'
PATH = ...
# WARNING: Assumed that icon_name - VALID resource ID
# It can be determined in loop when enumerating resources:
# if exception at CreateIconFromResource raised than this code appropriate
# otherwise resource is standard icon and first code snippet can be used.
# If resources Id exactly known then it can be hardcoded as in this code
icon_name = 1
try:
hlib = win32api.LoadLibrary(PATH)
# This part almost identical to C++
hResInfo = ctypes.windll.kernel32.FindResourceW(hlib, icon_name, win32con.RT_ICON)
size = ctypes.windll.kernel32.SizeofResource(hlib, hResInfo)
rec = win32api.LoadResource(hlib, win32con.RT_ICON, icon_name)
mem_pointer = ctypes.windll.kernel32.LockResource(rec)
# And this is some differ (copy data to Python buffer)
binary_data = (ctypes.c_ubyte * size)()
libc.memcpy(binary_data, mem_pointer, size)
# Save it
with open("icon.png", "wb") as test_file:
test_file.write(bytearray(binary_data))
except pywintypes.error as error:
print "ERROR: %s" % error.strerror
raise
</code></pre>
<hr/>
<p><strong>更新</strong>:</p>
<p>自动查找非图标资源并将其提取到名为“Resource_XX”的文件的代码:</p>
<pre><code># Same IMPORT's as previously should be used
# All Windows backslashes must be escaped to LoadLibrary worked correctly '\' -> '\\'
PATH = ...
def extract(rec):
try:
hicon = win32gui.CreateIconFromResource(rec, True)
except pywintypes.error as error:
# Check on appropriate error
if error.winerror != 6:
raise
print("Resource %2d isn't .ico, extract" % icon_name)
# This part almost identical to C++
hResInfo = ctypes.windll.kernel32.FindResourceW(hlib, icon_name, win32con.RT_ICON)
size = ctypes.windll.kernel32.SizeofResource(hlib, hResInfo)
mem_pointer = ctypes.windll.kernel32.LockResource(rec)
# And this is some differ (copy data to Python buffer)
binary_data = (ctypes.c_ubyte * size)()
libc.memcpy(binary_data, mem_pointer, size)
# Save it
with open("Resource_%s.png" % icon_name, "wb") as extract_file:
extract_file.write(bytearray(binary_data))
else:
info = win32gui.GetIconInfo(hicon)
bminfo = win32gui.GetObject(info[3])
print("Resource %2d is .ico: 0x%08X -> %d %d " %
(icon_name, hicon, bminfo.bmWidth, bminfo.bmHeight))
try:
hlib = win32api.LoadLibrary(PATH)
icon_names = win32api.EnumResourceNames(hlib, win32con.RT_ICON)
for icon_name in icon_names:
rec = win32api.LoadResource(hlib, win32con.RT_ICON, icon_name)
extract(rec)
except pywintypes.error as error:
print "ERROR: %s" % error.strerror
raise
</code></pre>