I need to extract all the icons from EXE and save them as files on the disk, but I cannot use the simplest solution ( ExtractIconEx ), because I need to extract ICO files that save large icons, even if the code runs on Windows-based systems XP. I will then extract the necessary icons (128x128 and other Vista-sized icons) using different code, but I need a way to extract all the icons with all their resources, since they are in the EXE, regardless of whether my computer is running XP, Vista or win7.
So far I know that the icons are in RT_GROUP_ICONS .
I know that some people should have done this before in Delphi, because utilities like IcoFX and the resource finder seem to have done this. I once remember that I saw an open source Delphi tool that would do this, but that was many years ago.
To reformulate the problem with ExtractIconEx - it will not get access to the entire .ico file, it will extract only the supported icon resource formats, which always support the same resolution (size) supported by the platform. So, for example, on XP, the 32x32 or 48x48 icon will be extracted, but not the 128x128 icon in Vista format.
Update: This is a modified version of the accepted answer that solves the problem of the future. if some function that we call should disappear from User32.dll in a future version of Windows, I would like it to fail more elegantly than not loading my entire application.
unit ExtractIconUtils; interface uses Graphics,Forms,Windows; //---------------------------------------------------------------------------- // ExtractIcons // Call "private" MS Api to extract Icon file. This calls a publically // documented function marked as deprecated in the MSDN documentation. // It was no doubt Not Originally Intended to be documented, or publically // accessed, but it provides functionality that its hard to live without. // It exists on Windows 2000, XP, Vista, and Windows7, but might not exist // in some future Windows version (released after year 2011). // // uses global hUserDll : THandle; //---------------------------------------------------------------------------- function ExtractIcons(exeFilename,icoOutFileName:String;icoSize:Integer):Boolean; var hUserDll : THandle; implementation function ExtractIcons(exeFilename,icoOutFileName:String;icoSize:Integer):Boolean; const {$ifdef UNICODE} ExtractProcName='PrivateExtractIconsW'; {$else} ExtractProcName='PrivateExtractIconsA'; {$endif} type TExtractFunc = function(lpszFile: PChar; nIconIndex, cxIcon, cyIcon: integer; phicon: PHANDLE; piconid: PDWORD; nicon, flags: DWORD): DWORD; stdcall; var hIcon : THandle; nIconId : DWORD; Icon : TIcon; PrivateExtractIcons:TExtractFunc; begin result := false; if (hUserDll<4) then begin hUserDll := LoadLibrary('user32.dll'); if (hUserDll<4) then exit; end; { PrivateExtractIcons: MSDN documentation says that this function could go away in a future windows version, so we must try to load it, and if it fails, return false, rather than doing a static DLL import. } PrivateExtractIcons := GetProcAddress(hUserDll, ExtractProcName); if not Assigned(PrivateExtractIcons) then exit; //extract a icoSize x icoSize icon where icoSize is one of 256,128,64,48,32,16 if PrivateExtractIcons ( PWideChar(exeFilename), 0, icoSize, icoSize, @hIcon, @nIconId, 1, LR_LOADFROMFILE) <>0 then try Icon:=TIcon.Create; try Icon.Handle:=hIcon; Icon.SaveToFile(icoOutFileName); result := true; finally Icon.Free; end; finally DestroyIcon (hIcon); end; end ; initialization // none finalization if (hUserDll>4) then FreeLibrary(hUserDll); end.