Skip to content

Instantly share code, notes, and snippets.

@flyx
Created June 21, 2012 13:16
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save flyx/2965682 to your computer and use it in GitHub Desktop.
Save flyx/2965682 to your computer and use it in GitHub Desktop.
Updates the icon of a windows executable file.
import win32api, win32con
import os, os.path
import struct
import math
def checkPath(path, mode):
if not os.path.exists(path) or not os.path.isfile(path):
raise ValueError("{0} does not exist or isn't a file.".format(path))
if not os.access(path, mode):
raise ValueError("Insufficient permissions: {0}".format(path))
def updateExecutableIcon(executablePath, iconPath):
"""
Updates the icon of a Windows executable file.
"""
checkPath(executablePath, os.W_OK)
checkPath(iconPath, os.R_OK)
handle = win32api.BeginUpdateResource(executablePath, False)
icon = open(iconPath, "rb")
fileheader = icon.read(6)
# Read icon data
image_type, image_count = struct.unpack("xxHH", fileheader)
print "Icon file has type {0} and contains {1} images.".format(image_type, image_count)
icon_group_desc = struct.pack("<HHH", 0, image_type, image_count)
icon_sizes = []
icon_offsets = []
# Read data of all included icons
for i in range(1, image_count + 1):
imageheader = icon.read(16)
width, height, colors, panes, bits_per_pixel, image_size, offset =\
struct.unpack("BBBxHHLL", imageheader)
print "Image is {0}x{1}, has {2} colors in the palette, {3} planes, {4} bits per pixel.".format(
width, height, colors, panes, bits_per_pixel);
print "Image size is {0}, the image content has an offset of {1}".format(image_size, offset);
icon_group_desc = icon_group_desc + struct.pack("<BBBBHHIH",
width, # Icon width
height, # Icon height
colors, # Colors (0 for 256 colors)
0, # Reserved2 (must be 0)
panes, # Color planes
bits_per_pixel, # Bits per pixel
image_size, # ImageSize
i # Resource ID
)
icon_sizes.append(image_size)
icon_offsets.append(offset)
# Read icon content and write it to executable file
for i in range(1, image_count + 1):
icon_content = icon.read(icon_sizes[i - 1])
print "Read {0} bytes for image #{1}".format(len(icon_content), i)
win32api.UpdateResource(handle, win32con.RT_ICON, i, icon_content)
win32api.UpdateResource(handle, win32con.RT_GROUP_ICON, "MAINICON", icon_group_desc)
win32api.EndUpdateResource(handle, False)
# Use some files I found lying around
updateExecutableIcon("example.exe", "test.ico")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment