Search code examples
pythoniconsexepywin32

How do you load an embedded icon from an exe file with PyWin32?


I have an exe file generated with py2exe. In the setup.py I specify an icon to be embedded in the exe:

windows=[{'script': 'my_script.py','icon_resources': [(0, 'my_icon.ico')], ...

I tried loading the icon using:

hinst = win32api.GetModuleHandle(None)
hicon = win32gui.LoadImage(hinst, 0, win32con.IMAGE_ICON, 0, 0, win32con.LR_DEFAULTSIZE)

But this produces an (very unspecific) error:
pywintypes.error: (0, 'LoadImage', 'No error message is available')

If I try specifying 0 as a string

hicon = win32gui.LoadImage(hinst, '0', win32con.IMAGE_ICON, 0, 0, win32con.LR_DEFAULTSIZE)

then I get the error:
pywintypes.error: (1813, 'LoadImage', 'The specified resource type cannot be found in the image file.')

So, what's the correct method/syntax to load the icon?
Also please notice that I don't use any GUI toolkit - just the Windows API via PyWin32.


Solution

  • @efotinis: You're right.

    Here is a workaround until py2exe gets fixed and you don't want to include the same icon twice:

    hicon = win32gui.CreateIconFromResource(win32api.LoadResource(None, win32con.RT_ICON, 1), True)
    

    Be aware that 1 is not the ID you gave the icon in setup.py (which is the icon group ID), but the resource ID automatically assigned by py2exe to each icon in each icon group. At least that's how I understand it.

    If you want to create an icon with a specified size (as CreateIconFromResource uses the system default icon size), you need to use CreateIconFromResourceEx, which isn't available via PyWin32:

    icon_res = win32api.LoadResource(None, win32con.RT_ICON, 1)
    hicon = ctypes.windll.user32.CreateIconFromResourceEx(icon_res, len(icon_res), True,
        0x00030000, 16, 16, win32con.LR_DEFAULTCOLOR)