SHGetFileInfoW not modifying reference passed into function

43 views Asked by At

I'm trying to create my own version of a file explorer in python. I'm stuck trying to get a file's associated icon.

Currently I'm using the SHGetFileInfoW imported from the ctype library. Below is my code. I tried to look at the documentation here and here but without examples I honestly they're a little too verbose and the lack of examples makes it hard to follow along. When I run my program with breakpoints and inspect fileInfo the values inside are not modified by the function call to SHGetFileInfoW, am I passing fileInfo correctly? or am I messing up somewhere else?

import ctypes
from ctypes import wintypes

SHGFI_ICON = 0x000000100
SHGFI_SMALLICON = 0x000000001
SHGFI_LARGEICON = 0x000000000
SHGFI_ATTRIBUTES = 0x000000800
SHIL_JUMBO = 0x0004

class SHFILEINFO(ctypes.Structure):
    _fields_ = [
        ("hIcon", wintypes.HANDLE),
        ("iIcon", ctypes.c_int),
        ("dwAttributes", wintypes.DWORD),
        ("szDisplayName", ctypes.c_char * 260),
        ("szTypeName", ctypes.c_char * 80)
    ]

def get_file_icon(file_path, large_icon=True):
    # Initialize COM library
    ctypes.windll.ole32.CoInitialize(0)

    # Create SHFILEINFO structure
    fileInfo = SHFILEINFO()

    # Specify size of SHFILEINFO structure
    uFlags = SHGFI_ICON | SHGFI_ATTRIBUTES

    # Call SHGetFileInfo to get the file icon
    try:
        ctypes.windll.shell32.SHGetFileInfoW(file_path, 0, ctypes.byref(fileInfo), ctypes.sizeof(fileInfo), uFlags)
    except Exception as e:
        print(e)

    # Create a copy of the icon to prevent resource leak
    icon_copy = ctypes.windll.user32.CopyIcon(fileInfo.hIcon)

    # Destroy the original icon to free resources
    ctypes.windll.user32.DestroyIcon(fileInfo.hIcon)

    # Uninitialize COM library
    ctypes.windll.ole32.CoUninitialize()

    return icon_copy

def save_icon_to_file(icon_handle, output_path):
    # Save the icon to a file
    ctypes.windll.shell32.Shell_NotifyIconW(0x00000003, icon_handle, output_path)

# Example usage:
file_path = "./blah.txt"
icon_handle = get_file_icon(file_path, large_icon=True)
output_path = "extracted_icon.ico"
save_icon_to_file(icon_handle, output_path)

0

There are 0 answers