Come estrarre le icone .ico da un file .exe in Windows: API, Python e .NET

Ultimo aggiornamento: 09/10/2025
Autore: Isaac
  • L'API di Windows consente di ottenere HICON e leggere i pixel con GetDIBits (BGRA).
  • En Python, ctypes copre ExtractIconExW e la conversione in immagini con Pillow.
  • .NET semplifica la visualizzazione dell'icona associata a un file con ImageList + ListView.
  • Gestisce gli handle GDI e l'ordine dei canali per evitare perdite ed errori.

Utilizzare le immagini come icone personalizzate per le cartelle in Windows 11

Se lavori in Windows, prima o poi vorrai estrarre un'icona da un file eseguibile o .ico per riutilizzarla in un'altra app, in un elenco o per i tuoi test. Esistono diversi modi per farlo nell'ecosistema Windows: l'API nativa (ExtractIconExW, GetDIBits…), Python con ctypes, .NET con Icon.ExtractAssociatedIcon e persino soluzioni veterane nel classico Visual BasicOgnuno ha le sue sfumature e vantaggi. Puoi rivedere un Guida alle utilità NirSoft.

In questa guida, abbiamo riunito tutti questi elementi in un unico posto. Vedrai tutto, da come chiedere a Windows il HICON “piccolo” e “grande” che espone un file .exe o .ico, come leggere il bitmap in formato BGRA, convertirlo in RGBA se necessario per PyGame o Pillow e come visualizzare l'icona associata a un file in un ListView di Windows Forms con un ImageListEsaminiamo anche un approccio VB classico per elencare e salvare le icone e discutiamo considerazioni pratiche.

Cosa c'è dentro un file .ico e .exe: dimensioni e dove appaiono

Una singola icona può includere diverse immagini interne di diverse dimensioni (16x16, 32x32, 48x48, ecc.). In Windows, è comune che le cosiddette icone “piccolo” (16×16) sono utilizzati in Windows e in Explorer, dove le cache come Windows thumbs.db può memorizzare miniature, mentre il “grande” (32×32) Vengono visualizzati nella barra delle applicazioni e quando si alterna con Alt+Tab. Gli eseguibili (.exe) e le librerie (.dll) memorizzano le icone come mezzie i file .ico stessi sono contenitori per più risoluzioni e profondità di colore.

L'API di Windows semplifica questa lettura: con ExtractIconExW (At shell32.dll) puoi richiedere l'icona piccola o grande che un file espone, sia essa un .exe o un .ico. Quella funzione restituisce handle HICON pronti per essere disegnati o, se vuoi andare oltre, per leggere la bitmap sottostante e manipolare i pixel.

Se hai bisogno di materiale grezzo (ad esempio byte bitmap da elaborare con le tue librerie), il percorso include Ottieni informazioni sull'icona per passare da HICON al tuo HBITMAP e OttieniDIBits per scaricare il contenuto in un buffer da te controllato. Questo ti dà il controllo completo: dimensione esatta, ordine dei byte, trasparenza e formattazione.

Dobbiamo tenere presente il formato interno che Windows restituisce in questi casi: normalmente abbiamo a che fare con 32 bit per pixel in BGRA (blu, verde, rosso e alfa). Questa differenza con l'RGBA convenzionale è importante se si prevede di passare l'immagine a motori o librerie che prevedono un ordine dei canali diverso.

La chiave è capire che l'API restituisce i dati nell'ordine di lettura di GDI. Con l'intestazione corretta e l'altezza negativa, è possibile ricevere l'immagine in top-down (dall'alto verso il basso) e quindi facilitarne l'uso diretto in altre librerie senza dover capovolgere il buffer.

dimensioni e posizioni delle icone in Windows

Estrazione di icone con Python e l'API di Windows (ctypes): da HICON a byte di immagine

Se stai usando Python su Windows, il percorso più diretto oggi è quello di estrarre ctypes per chiamare l'API nativaPotremmo pensare a pywin32, ma c'è un dettaglio importante: pywin32 non espone OttieniDIBits, e quella funzione è necessaria per ottenere i pixel reali da un HICONPertanto, ctypes è il modo pratico per definire strutture, prototipi e chiamate esattamente come previsto dall'API di Windows.

La sequenza tipica è la seguente: creare un Compatibile con DC (CreateCompatibleDC), chiamata ExtractIconExW Per ottenere l'icona piccola o grande, risolvi i bitmap di colore e maschera con Ottieni informazioni sull'icona, preparare un BITMAPINFO con intestazione a 32 bit, indica l'altezza negativa per le coordinate dall'alto verso il basso e infine scarica i pixel con GetDIBits in un buffer Python (ctypes.create_string_buffer).

da ctypes importa byref, sizeof da ctypes importa c_int, c_void_p da ctypes importa create_string_buffer da ctypes.wintypes importa BOOL, BYTE, DWORD, HBITMAP, HDC, HGDIOBJ, HICON, LONG, LPCWSTR, LPVOID, UINT, PAROLA
import ctypes # Costanti comuni BI_RGB = 0 DIB_RGB_COLORS = 0 # Strutture minime per GDI class ICONINFO(ctypes.Structure): _fields_ = class RGBQUAD(ctypes.Structure): _fields_ = class BITMAPINFOHEADER(ctypes.Structure): _fields_ = class BITMAPINFO(ctypes.Structure): _fields_ = # DLL shell32 = ctypes.WinDLL('shell32', use_last_error=True) user32 = ctypes.WinDLL('user32', use_last_error=True) gdi32 = ctypes.WinDLL('gdi32', use_last_error=True) # Prototipi essenziali shell32.ExtractIconExW.argtypes = shell32.ExtractIconExW.restype = UINT user32.GetIconInfo.argtypes = user32.GetIconInfo.restype = BOOL user32.DestroyIcon.argtypes = user32.DestroyIcon.restype = BOOL gdi32.CreateCompatibleDC.argtypes = gdi32.CreateCompatibleDC.restype = HDC gdi32.GetDIBits.argtypes = gdi32.GetDIBits.restype = c_int gdi32.DeleteObject.argtypes = gdi32.DeleteObject.restype = BOOL # Semplice enumerazione per le dimensioni classe IconSize: SMALL = 1 LARGE = 2 @staticmethod def to_wh(size): return {IconSize.SMALL: (16, 16), IconSize.LARGE: (32, 32)} # Funzione di alto livello (schizzo) def extract_icon(filename, size): dc = gdi32.CreateCompatibleDC(0) if dc == 0: raise ctypes.WinError() hicon = HICON() # Ordiniamo il grande o il piccolo come appropriato out_large = byref(hicon) if size == IconSize.LARGE else None out_small = byref(hicon) if size == IconSize.SMALL else None got = shell32.ExtractIconExW(filename, 0, out_large, out_small, 1) if got != 1: raise ctypes.WinError() info = ICONINFO() if not user32.GetIconInfo(hicon, byref(info)): user32.DestroyIcon(hicon) raise ctypes.WinError() w, h = IconSize.to_wh(size) bmi = BITMAPINFO() ctypes.memset(byref(bmi), 0, sizeof(bmi)) bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER) bmi.bmiHeader.biWidth = w bmi.bmiHeader.biHeight = -h # negativo per top-down bmi.bmiHeader.biPlanes = 1 bmi.bmiHeader.biBitCount = 32 bmi.bmiHeader.biCompression = BI_RGB bmi.bmiHeader.biSizeImage = w * h * 4 bit = create_string_buffer(bmi.bmiHeader.biSizeImage) copied = gdi32.GetDIBits(dc, info.hbmColor, 0, h, bits, byref(bmi), DIB_RGB_COLORS) if copied == 0: # Pulizia minima if info.hbmColor: gdi32.DeleteObject(info.hbmColor) if info.hbmMask: gdi32.DeleteObject(info.hbmMask) user32.DestroyIcon(hicon) raise ctypes.WinError() # Pulisci GDI e HICON if info.hbmColor: gdi32.DeleteObject(info.hbmColor) if info.hbmMask: gdi32.DeleteObject(info.hbmMask) user32.DestroyIcon(hicon) return bits # bytes BGRA

Con quanto sopra puoi ora ottenere l'icona piccola o grande di qualsiasi eseguibile. Ad esempio, se vuoi provare con l'interprete Python stesso (percorso disponibile in sys.eseguibile), basta estrarre entrambe le dimensioni e lavorare con i loro buffer.

# Esempio di utilizzo import sys small_icon = extract_icon(sys.executable, IconSize.SMALL) large_icon = extract_icon(sys.executable, IconSize.LARGE)

Il risultato è un blocco di byte in cui Ogni pixel occupa 4 byte in BGRAIn 16×16 avrai 16×16×4 = 1024 byte e in 32×32, 4096. L'ordine è riga per riga e colonna per colonna, dall'alto verso il basso e da sinistra a destra se hai utilizzato un'altezza negativa nell'intestazione, il che rende più facile leggere l'indice corretto per ciascuno (x, y).

  Come controllare Windows 11 dal tuo cellulare: guida completa e opzioni consigliate

Se si desidera convalidare la dimensione, è possibile stampare la lunghezza del buffer 16x16 e verificare che siano 1024 byteQuesto controllo ti evita sorprese quando lavori con risorse che includono diverse risoluzioni e profondità di colore.

Per visualizzare pixel per pixel e apprezzare l'ordine di lettura, una tecnica didattica è quella di utilizzare PyGame: si esamina il buffer riga per riga, si converte ogni BGRA in RGBA e si disegna con set_at. È anche possibile introdurre un piccolo ritardo iniziale per “vedere” come è riempita l’icona sullo schermo.

# Rendi l'icona 32x32 con PyGame, convertendo BGRA -> RGBA da winicon import IconSize, extract_icon import pygame import sys pygame.init() screen = pygame.display.set_mode((320, 240)) icon_size = IconSize.LARGE w, h = IconSize.to_wh(icon_size) icon_large = extract_icon(sys.executable, icon_size) rendered = False offset_x, offset_y = 50, 50 while True: for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() screen.fill((0, 0, 0)) for row in range(h): for col in range(w): index = row * w * 4 + col * 4 b, g, r, a = icon_large color = (r, g, b, a) screen.set_at((offset_x + col, offset_y + riga), colore) se non renderizzato: pygame.time.wait(10) pygame.display.flip() renderizzato = True

In pratica, non sempre sarà necessario toccare manualmente i pixel. Per salvare l'icona su disco come immagine, Cuscino (PIL) rende la vita molto più semplice: si crea l'immagine dai byte con modalità 'RGBA' indicando che l'input è 'BGRA' e il salva come BMP, PNG o qualsiasi altro formato che ti sia più comodoUn adattatore come win32_icon_to_image(icon_bits, size) centralizza questa conversione per te.

# Conversione del buffer BGRA in un'immagine PIL e salvataggio da PIL import Image def win32_icon_to_image(icon_bits, size): w, h = IconSize.to_wh(size) img = Image.frombytes('RGBA', (w, h), icon_bits, 'raw', 'BGRA') return img img_small = win32_icon_to_image(small_icon, IconSize.SMALL) img_large = win32_icon_to_image(large_icon, IconSize.LARGE) img_small.save('python1.bmp') img_large.save('python2.bmp')

Estrazione con Python e API di Windows

Visualizza l'icona associata a un file in .NET (WinForms): ListView + ImageList

Un'altra esigenza comune è quella di mostrare, insieme al nome di ogni file, il icona che Windows associa alla sua estensione (ad esempio, .docx con l'icona di Word). In WinForms puoi risolverlo con Icona.EstraiIconaAssociata e memorizzare i risultati in un Elenco immagini che è vincolato a un ListView impostato sulla vista SmallIcon.

L'idea è di attraversare i file in una directory e per ognuno controllare se si ha già un'immagine nell'ImageList con chiave uguale all'estensione; in caso contrario, estrai l'icona e aggiungila. In questo modo eviti i duplicati e velocizzerai il caricamento. Per l'elemento ListView, assegni la proprietà ImageKey con quell'estensione e aggiungi l'elemento. Se qualcosa non va, puoi usare un fallback come Icone di sistema.WinLogo.

ListView listView1 = new ListView(); ImageList imageList1 = new ImageList(); listView1.SmallImageList = imageList1; listView1.View = View.SmallIcon; // Esegue un ciclo tra i file (richiede l'utilizzo di System.IO) var dir = new System.IO.DirectoryInfo(@"C:\\"); foreach (var file in dir.GetFiles()) { var item = new ListViewItem(file.Name); var key = file.Extension; if (!imageList1.Images.ContainsKey(key)) { var icon = System.Drawing.Icon.ExtractAssociatedIcon(file.FullName); imageList1.Images.Add(key, icon); } item.ImageKey = key; listView1.Items.Add(item); }

Per compilarlo velocemente, incolla il codice in un Moduli di Windows, crea e configura ListView e ImageList nel costruttore o nell'evento Load e ricorda di importare lo spazio dei nomi Sistema.IONon è necessario occuparsi manualmente di HICON o pixel; qui ci si affida interamente a associazioni di icone di sistema.

  Errore 0xC0000142 in Office: cause, significato e soluzioni per ripristinare i programmi

Approccio classico con Visual Basic (estrattore/visualizzatore e salvataggio in BMP)

Prima di .NET e dei wrapper moderni, molte utility in VB 4/5/6 svolgevano già questo lavoro chiamando l'API: Estrai icona da shell32 per ottenere HICON, DisegnaIcona dipingere in un PictureBox, e BitBlt per copiare su un'altra superficie e creare una striscia di miniature. Questi programmi enumeravano le icone di un file .exe o .dll incrementando il indice delle icone finché la funzione non ha smesso di restituire risultati.

Il flusso tipico era: dopo aver selezionato un file, iniziare dall'indice 0 e, mentre Estrai icona restituisce un handle valido, lo disegna nel PictureBox, aggiorna e passa all'indice successivo. In parallelo, con BitBlt, i 32x32 sono stati copiati su una seconda superficie in posizioni di offset (ad esempio, su X = 2 + indice × cella) per visualizza tutte le icone incorporate a colpo d'occhio.

Per risparmiare, VB ha offerto due percorsi con Salva immagine: memorizza la proprietà Picture così com'è o la proprietà Image (quest'ultima sempre come BMP). Inoltre, alcuni moduli hanno aggiunto un selettore di file con filtri per estensione per .ico, .bmp, .exe, .dll e altri, e mostrava persino un'anteprima se il file era un'immagine.

Questo approccio è ancora valido per comprendere come interagire con l'API dei linguaggi Windows "tradizionali". Tuttavia, se hai bisogno dell'API oggi, buffer di pixel, è meglio usare GDI e GetDIBits (o, nel moderno .NET, metodi che serializzano l'immagine) invece di affidarsi solo a DisegnaIcona sui controlli.

Dettagli importanti: dimensione, ordine dei byte e lettura di righe/colonne

Quando si recuperano pixel con GetDIBits, specificando biHeight come negativo si rende l'origine delle coordinate l'angolo in alto a sinistra, che è ciò che molte librerie grafiche si aspettano. In caso contrario, otterrai un buffer dal basso verso l'alto (dal basso verso l'alto) e dovrai invertire i blocchi per righe.

Nel 16×16, la prima riga occupa 16×4 = 64 byte (4 per pixel). Pertanto, lo spostamento alla riga n è n × 64 e quello alla colonna m è m × 4. In 32 × 32, ogni riga è 128 byte e il totale è 4096. L'ordine BGRA (B, G, R, A) è ciò che queste chiamate GDI restituiscono; se la libreria di destinazione desidera RGBA, sarà necessario riordinare i canali come è stato fatto con PyGame o indicarlo quando si crea l'immagine con Pillow.

  Impostare backup automatici su un disco rigido esterno in Windows 11

Se stai manipolando la trasparenza, il canale alfa sarà il quarto byte del pixel. Ricorda che anche le icone usano un maschera (hbmMask); quando si lavora con BGRA a 32 bit, la trasparenza è solitamente già rappresentata nell'alfa del hbmColor, quindi la maschera può essere ignorata per gli usi comuni.

Icone in Risorse e Sostituzione: Considerazioni Rapide

Gli eseguibili e le librerie salvano le loro icone come mezziÈ possibile estrarli tramite l'API come spiegato oppure, se si preferisce qualcosa di visivo, esistono editor di risorse e utilità con interfacce grafiche che consentono di farlo. sostituire o esportare icone. Se si intende automatizzare, l'approccio programmatico con HICON, GetIconInfo e GetDIBits offre controllo e riproducibilità completi.

Per leggere le icone “associate” alle estensioni (senza estrarre risorse dal file .exe stesso), .NET semplifica il lavoro con Icona.EstraiIconaAssociataQuesto metodo si basa sulle associazioni del registro e restituisce l'icona che il sistema visualizzerebbe per ciascun file, il che è ideale per elenchi, esploratori e visualizzatori.

Buone pratiche e pulizia delle risorse

Lavorare con GDI implica la gestione maniglie e memoria esplicitamente. Ogni volta che si ottiene un HICON o un HBITMAP è necessario prevedere il suo ciclo di vita: distruggere l'HICON con DistruggiIcona e rilasciare le bitmap con EliminaoggettoDimenticarlo può portare a perdite di risorse che, nelle applicazioni con molte chiamate, si traducono in perdite e comportamento irregolare.

In Python/ctypes è conveniente incapsulare la pulizia in una piccola funzione o in un gestore del contestoAssicurati di eseguire sempre la pulizia sui rami bug, soprattutto se OttieniDIBits restituisce 0 o sì ExtractIconExW non restituisce il numero previsto di icone. Inoltre, verificare che il controller di dominio restituito da CreateCompatibleDC sia valido prima di continuare.

Quando scegliere ciascun approccio

Se hai solo bisogno di visualizzare l'icona "che Windows visualizzerebbe" per un file, .NET con ExtractAssociatedIcon È semplice ed efficace. Se vuoi leggere la bitmap effettiva da un'icona incorporata in un file .exe o .ico per modificarla, convertirla o salvarla da soli, il API con ctypes Offre tutto il controllo di cui hai bisogno. Per gli strumenti legacy o la prototipazione rapida, il classico approccio VB rimane illustrativo e funzionale nel suo contesto.

D'altra parte, se l'obiettivo è salvare le icone come immagini con livello alfa e senza perdite, prendi in considerazione formati come PNG Utilizzando Pillow, è possibile fornire l'ordinamento dei canali appropriato. Il formato BMP è semplice e ampiamente supportato, ma se si preferisce la compressione e la trasparenza, PNG o ICO (in caso di riconfezionamento) potrebbero essere più appropriati.

Integrando API nativa, Python e .NET, è possibile coprire tutto, dal semplice caso di visualizzazione delle icone associate all'estensione all'estrazione del Byte BGRA Con il pieno controllo su dimensioni, trasparenza e ordine di lettura, nonché la possibilità di elencare le icone incorporate in eseguibili legacy o moderni, questa varietà di percorsi ti consentirà di risolvere qualsiasi problema, dai visualizzatori e dagli elenchi alle pipeline di esportazione e modifica delle icone.

Utilità NirSoft-5
Articolo correlato:
La guida definitiva alle utilità NirSoft: oltre 250 strumenti gratuiti per migliorare Windows