从EXE中提取所有图标,而不使用ExtractIconEx [英] Extract all icons from an EXE without using ExtractIconEx

查看:896
本文介绍了从EXE中提取所有图标,而不使用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆