从EXE中提取所有图标,而不使用ExtractIconEx [英] Extract all icons from an EXE without using ExtractIconEx
问题描述
我需要从EXE中提取所有图标并将其保存为磁盘文件,但是我无法使用最简单的解决方案( ExtractIconEx ),因为我需要以保留大尺寸图标的方式提取ICO文件,即使代码运行在运行Windows XP的系统。随后,我将使用其他代码提取想要的图标(128x128和其他vista大小图标),但是我需要一种方法来提取所有图标,其所有资源,因为它们存在于EXE中,而不管PC是否运行我的代码在运行XP,Vista或Win7。
I need to extract all icons from an EXE and save them as disk files, but I cannot use the simplest solution (ExtractIconEx) because I need to extract the ICO files in a way that preserves the large-size icons, even when the code runs on systems running Windows XP. I will later extract the wanted icons (128x128 and other vista size icons) using other code, but I need a way to extract all icons, with all their resources, as they are present in the EXE, regardless of whether the PC my code runs on is running XP, Vista, or Win7.
到目前为止,我知道图标在 RT_GROUP_ICONS 。
So far I know that icons are in the RT_GROUP_ICONS.
我知道有些人在德尔福之前必须这样做,因为实用程序像IcoFX和资源浏览器似乎已经这样做了。我曾经记得看到一个完全开放源码的Delphi工具,可以这样做,但是这是几年前。
I know some people must have done this before in Delp because utilities like IcoFX and resource-explorer seem to have done this. I once remember seeing a completely open-source Delphi tool that would do it, but it was years ago.
重述我与ExtractIconEx有关的问题 - 它不会访问整个.ico文件,它只会提取支持的图标资源格式,这是平台支持的单一分辨率(大小)。所以在XP上,例如,它将提取32x32或48x48图标,但不会提供Vista格式的128x128图标。
To restate the problem I have with ExtractIconEx - It will not access the entire .ico file, it will only extract the supported icon resource formats, which ever single resolution (size) that the platform supports. So on XP, for example, it will extract a 32x32 or 48x48 icon, but not a Vista-format 128x128 icon.
更新:是接受答案的修改版本,解决了我未来的担忧。如果不知何故,我们打电话的功能是在以后的Windows版本中从User32.dll中消失,我希望它能够更加优雅地失败,而不是加载整个应用程序。
Update: This is a modified version of the accepted answer that solves my future-proofing worry. if somehow the function we are calling was to disappear from User32.dll in a future windows version, I would want it to fail more gracefully, than to fail to load up my whole 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.
推荐答案
PrivateExtractIcons
功能可以帮助您。您可以指定要提取的图标的大小:
The PrivateExtractIcons
function can help you. You can specify the size of the icon which you want to extract:
{$IFDEF UNICODE}
function PrivateExtractIcons(lpszFile: PChar; nIconIndex, cxIcon, cyIcon: integer; phicon: PHANDLE; piconid: PDWORD; nicon, flags: DWORD): DWORD; stdcall ; external 'user32.dll' name 'PrivateExtractIconsW';
{$ELSE}
function PrivateExtractIcons(lpszFile: PChar; nIconIndex, cxIcon, cyIcon: integer; phicon: PHANDLE; piconid: PDWORD; nicon, flags: DWORD): DWORD; stdcall ; external 'user32.dll' name 'PrivateExtractIconsA';
{$ENDIF}
procedure TMainForm.Button1Click(Sender: TObject);
var
hIcon : THandle;
nIconId : DWORD;
Icon : TIcon;
begin
//Extract a 128x128 icon
if PrivateExtractIcons ('C:\Users\Public\Documents\RAD Studio\Projects\2010\Aero Colorizer\AeroColorizer.exe', 0, 128, 128, @hIcon, @nIconId, 1, LR_LOADFROMFILE) <>0 then
try
Icon:=TIcon.Create;
try
Icon.Handle:=hIcon;
Icon.SaveToFile(ExtractFilePath(ParamStr(0))+'Aicon.ico');
finally
Icon.Free;
end;
finally
DestroyIcon (hIcon);
end;
end ;
这篇关于从EXE中提取所有图标,而不使用ExtractIconEx的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!