如何使用Delphi或Lazarus确定dll文件是作为x64位还是x86位编译的

8

我希望能够使用Delphi 2007+或Lazarus(Win64)来确定一个dll文件是以x64还是x86编译的。


我找到了以下信息,但还没有时间消化它: http://www.tech-archive.net/Archive/Development/microsoft.public.win32.programmer.tools/2006-12/msg00011.html在前面的链接文章中提到的这个链接: http://www.delphidabbler.com/articles?article=8&part=2 提供了Delphi源代码来解析文件头,可以识别16位和32位,但不支持64位。该代码可以在Delphi 2007上运行,但不能在Delphi2010或Lazarus上运行——至少需要进行比我有时间或经验更多的修改。 - TheSteven
2个回答

18

你应该阅读并解析PE头。

像这样:

function Isx64(const Strm: TStream): Boolean;
const
  IMAGE_FILE_MACHINE_I386     = $014c; // Intel x86
  IMAGE_FILE_MACHINE_IA64     = $0200; // Intel Itanium Processor Family (IPF)
  IMAGE_FILE_MACHINE_AMD64    = $8664; // x64 (AMD64 or EM64T)
  // You'll unlikely encounter the things below:
  IMAGE_FILE_MACHINE_R3000_BE = $160;  // MIPS big-endian
  IMAGE_FILE_MACHINE_R3000    = $162;  // MIPS little-endian, 0x160 big-endian
  IMAGE_FILE_MACHINE_R4000    = $166;  // MIPS little-endian
  IMAGE_FILE_MACHINE_R10000   = $168;  // MIPS little-endian
  IMAGE_FILE_MACHINE_ALPHA    = $184;  // Alpha_AXP }
  IMAGE_FILE_MACHINE_POWERPC  = $1F0;  // IBM PowerPC Little-Endian
var
  Header: TImageDosHeader;
  ImageNtHeaders: TImageNtHeaders;
begin
  Strm.ReadBuffer(Header, SizeOf(Header));
  if (Header.e_magic <> IMAGE_DOS_SIGNATURE) or
     (Header._lfanew = 0) then
    raise Exception.Create('Invalid executable');
  Strm.Position := Header._lfanew;

  Strm.ReadBuffer(ImageNtHeaders, SizeOf(ImageNtHeaders));
  if ImageNtHeaders.Signature <> IMAGE_NT_SIGNATURE then
    raise Exception.Create('Invalid executable');

  Result := ImageNtHeaders.FileHeader.Machine <> IMAGE_FILE_MACHINE_I386;
end;

感谢您的回复。 不幸的是,这需要使用JCL才能工作。我还没有将JCL添加到我的Delphi 2007中,但如果看起来是唯一的解决方案,我可能会添加它。 - TheSteven
1
你的更新版本在Delphi 2007和Delphi 2010中都能很好地工作。 一个优雅的解决方案 - 谢谢。 - TheSteven
1
请注意,这些常量在FPC上是以Windows单位表示的。(至少在2.4.0+版本中如此,不确定旧版本是否也是如此) - Marco van de Voort

5
您可以使用JCL中的JclPeImage。以下应用程序展示了如何使用它。

program Isx64ImageTest;

{$APPTYPE CONSOLE}

uses
  SysUtils, JclWin32, JclPEImage;

var
  PEImage: TJclPeImage;
begin
  PEImage := TJclPeImage.Create;
  try
    //usage is "Isx64ImageTest filename"
    PEImage.FileName := ParamStr(1);
    //print the machine value as string
    WriteLn(Format('Machine value of image %s is %s',
      [PEImage.FileName, PEImage.HeaderValues[JclPeHeader_Machine]]));
    //check for a special machine value
    case PEImage.LoadedImage.FileHeader^.FileHeader.Machine of
      IMAGE_FILE_MACHINE_I386:  begin end;
      IMAGE_FILE_MACHINE_AMD64: begin end;
      else
      begin
      end;
    end;
  finally
    PEImage.Free;
  end;
end.

1
如果您正在使用JCL,则有更简单的方法 - 使用PeMapImgTarget函数或PEImage.Target属性(在您的示例中)。无需自己分析头文件。 - Alex
尚未使用JCL,但最终可能会这样做。 我一直在试图镜像我的Delphi2007和Delphi2010组件,因为我计划迁移到Delphi2010。JCL是否可用于Delphi2010? - TheSteven

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接