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)