【问题标题】:How to detect Delphi compiler version in which exe was compiled?如何检测编译exe的Delphi编译器版本?
【发布时间】:2011-12-03 14:49:18
【问题描述】:

如何检测使用哪个版本的 Delphi 来编译预先存在的 .exe 文件?我不一定需要用代码来做这个。

我试过 PEiD,但它无法检测版本是否比 Delphi 7 新。

【问题讨论】:

    标签: delphi compiler-construction version


    【解决方案1】:

    下载IDR (Interactive Delphi Reconstructor) 的各种文件,将它们解压缩到一个文件夹并运行它。在 IDR 中加载您编译的可执行文件,它会告诉您可执行文件的编译版本(对我来说已被证明是准确的)。

    【讨论】:

    • 按预期工作。但是 D2010 支持不是免费的,目前不支持 D2010 的较新版本。但我的 exe 是在 D2007 中编译的 :)
    • D2010 文件实际上是免费的。出于某种原因,作者希望您通过电子邮件向他发送密码(我会在此处分发但可能是非法的)。
    • 我可以使用 IDR 加载 exe,但在哪里可以获得 delphi 版本信息?
    【解决方案2】:

    替代解决方案:

    XN Resource Editor 中打开您编译的可执行文件。在树中的“RC 数据”下,您会找到 DVCLAL。展开它并选择“语言中性”。您现在将看到一个无意义的字符串,它具有同样无意义的 HEX 等价物。

    这个 HEX 实际上标识了构建可执行文件的编译器版本。你可以用 Delphi 这个词谷歌这个 HEX,你应该很快就能确定 HEX 来自哪个编译器。

    享受吧!

    【讨论】:

    • 每个解决方案都是不同的,而不是相同的变体。据我了解,这个想法是为每个完全不同的解决方案提交一个答案。不是这样吗?
    • 很公平。我只是假设这是“标准做法”。可能将我自己对整洁分离的热爱归咎于他人。
    • @大卫:The official word on multiple answers。让社区投票赞成这两者。
    • @afrazier 你在那个元问题上读过 Jeff 的 cmets 吗?
    • 我认为这个字符串只标识了 Delphi 的版本(如 Enterprise、Professional),而不是它的版本。例如,XE2 Professional 和 2007 Professional 是一样的。也许对于旧版本(如 D3),区分版本很有用。
    【解决方案3】:

    您可以使用此来源为您提供大会信息。在主程序集中,您可以看到名称和版本,这将为您提供编译器的名称和版本。它是一个控制台应用程序,其中 param 1exe 文件。

    版本可以在这里查看:

    http://wiki.delphi-jedi.org/wiki/JEDI_Help:CompilerVersions

    查看 vbuild 使用的是哪个版本;即,

    12.xxxx - Delphi 2009 和 15.xxxx - Delphi XE

    但是,这仅适用于 XE。使用 XE2,exe 中的情况发生了变化。

     program versionchk;
    
        {$APPTYPE CONSOLE}
    
        uses
          ActiveX,
          Classes,
          Windows,
          Variants,
          ComObj,
          StrUtils,
          SysUtils;
    
        type
          TAssemblyIdentity=record
            &type : string;
            name    : string;
            language: string;
            processorArchitecture   : string;
            version : string;
            publicKeyToken: string;
          end;
    
          TRequestedExecutionLevel=record
            level    : string;
            uiAccess : string;
          end;
    
          TManifiestReader=class
          private
            FFileName: string;
            FManifest: AnsiString;
            FMainAssemblyIdentity: TAssemblyIdentity;
            FHasManifest: Boolean;
            FDependentAssembly: TAssemblyIdentity;
            FManifestVersion: string;
            FRequestedExecutionLevel: TRequestedExecutionLevel;
            procedure GetManifest;
            procedure LoadManifestData;
            function  VarNullToStr(Value:OleVariant):string;
          public
            property FileName : string read FFileName;
            property Manifest : AnsiString read FManifest;
            property ManifestVersion : string read FManifestVersion;
            property MainAssemblyIdentity : TAssemblyIdentity read FMainAssemblyIdentity;
            property DependentAssembly : TAssemblyIdentity read FDependentAssembly;
            property HasManifest : Boolean read FHasManifest;
            property RequestedExecutionLevel : TRequestedExecutionLevel read FRequestedExecutionLevel;
            constructor Create(const AFileName:string);
          end;
    
        { TReadManifiest }
    
        constructor TManifiestReader.Create(const AFileName: string);
        begin
          FFileName:=AFileName;
          FHasManifest:=False;
          GetManifest;
          LoadManifestData;
        end;
    
        procedure TManifiestReader.GetManifest;
        var
          hModule  : THandle;
          Resource : TResourceStream;
        begin
          FManifest:='';
          hModule:=LoadLibraryEx(PChar(FileName),0,LOAD_LIBRARY_AS_DATAFILE);
          try
             if hModule=0 then RaiseLastOSError;
             if FindResource(hModule, MakeIntResource(1), RT_MANIFEST)<>0 then
             begin
               Resource:=TResourceStream.CreateFromID(hModule,1,RT_MANIFEST);
               try
                 SetString(FManifest, PAnsiChar(Resource.Memory),Resource.Size);
                 FHasManifest:=True;
               finally
                 Resource.Free;
               end;
             end;
          finally
              FreeLibrary(hModule);
          end;
        end;
    
        procedure TManifiestReader.LoadManifestData;
        const
         assembly_namespace_V1='urn:schemas-microsoft-com:asm.v1';
         assembly_namespace_V2='urn:schemas-microsoft-com:asm.v2';
         assembly_namespace_V3='urn:schemas-microsoft-com:asm.v3';
        var
          XmlDoc : OleVariant;
          ns     : string;
          Node   : OleVariant;
        begin
          if Trim(FManifest)='' then exit;
          XmlDoc       := CreateOleObject('Msxml2.DOMDocument.6.0');
          XmlDoc.Async := False;
          try
            XmlDoc.LoadXML(FManifest);
            XmlDoc.SetProperty('SelectionLanguage','XPath');
    
            if (XmlDoc.parseError.errorCode <> 0) then
             raise Exception.CreateFmt('Error in Xml Data %s',[XmlDoc.parseError]);
    
            //set the namespaces alias
            ns := Format('xmlns:a=%s xmlns:b=%s xmlns:c=%s',[QuotedStr(assembly_namespace_V1),QuotedStr(assembly_namespace_V2),QuotedStr(assembly_namespace_V3)]);
            XmlDoc.setProperty('SelectionNamespaces', ns);
    
            //get the version of the manifest
            Node:=XmlDoc.selectSingleNode('/a:assembly/@manifestVersion');
            if not VarIsNull(Node) and not VarIsClear(Node) then
            FManifestVersion:=Node.text;
    
            Node:=XmlDoc.selectSingleNode('/a:assembly/a:assemblyIdentity');
            if not VarIsNull(Node) and not VarIsClear(Node) then
            begin
              FMainAssemblyIdentity.&type   :=Node.getAttribute('type');
              FMainAssemblyIdentity.name    :=Node.getAttribute('name');
              FMainAssemblyIdentity.language:=VarNullToStr(Node.getAttribute('language'));
              FMainAssemblyIdentity.version :=Node.getAttribute('version');
              FMainAssemblyIdentity.processorArchitecture:=VarNullToStr(Node.getAttribute('processorArchitecture'));
              FMainAssemblyIdentity.publicKeyToken       :=VarNullToStr(Node.getAttribute('publicKeyToken'));
            end;
    
            Node:=XmlDoc.selectSingleNode('/a:assembly/a:dependency/a:dependentAssembly/a:assemblyIdentity');
            if not VarIsNull(Node) and not VarIsClear(Node) then
            begin
              FDependentAssembly.&type   :=Node.getAttribute('type');
              FDependentAssembly.name    :=Node.getAttribute('name');
              FDependentAssembly.language:=VarNullToStr(Node.getAttribute('language'));
              FDependentAssembly.version :=Node.getAttribute('version');
              FDependentAssembly.processorArchitecture:=VarNullToStr(Node.getAttribute('processorArchitecture'));
              FDependentAssembly.publicKeyToken       :=VarNullToStr(Node.getAttribute('publicKeyToken'));
            end;
    
            Node:=XmlDoc.selectSingleNode('/a:assembly/b:trustInfo/b:security/b:requestedPrivileges/b:requestedExecutionLevel');
            if VarIsNull(Node) or VarIsClear(Node) then
              Node:=XmlDoc.selectSingleNode('/a:assembly/c:trustInfo/c:security/c:requestedPrivileges/c:requestedExecutionLevel');
            if not VarIsNull(Node) and not VarIsClear(Node) then
            begin
              FRequestedExecutionLevel.level   :=Node.getAttribute('level');
              FRequestedExecutionLevel.uiAccess:=VarNullToStr(Node.getAttribute('uiAccess'));
            end;
    
          finally
            XmlDoc:=Unassigned;
          end;
        end;
    
        function TManifiestReader.VarNullToStr(Value: OleVariant): string;
        begin
          if VarIsNull(Value) then
            Result:=''
          else
            Result:=VarToStr(Value);
        end;
    
        Var
          ManifestReader : TManifiestReader;
        begin
         try
            CoInitialize(nil);
            try
              ManifestReader:=TManifiestReader.Create(ParamStr(1));
              try
                //Writeln(ManifestReader.Manifest);
    
                Writeln('Manifest version '+ManifestReader.ManifestVersion);
                Writeln('Main Assembly Identity');
                Writeln('----------------------');
                Writeln('type     '+ManifestReader.MainAssemblyIdentity.&type);
                Writeln('name     '+ManifestReader.MainAssemblyIdentity.name);
                Writeln('language '+ManifestReader.MainAssemblyIdentity.language);
                Writeln('version  '+ManifestReader.MainAssemblyIdentity.version);
                Writeln('processorArchitecture '+ManifestReader.MainAssemblyIdentity.processorArchitecture);
                Writeln('publicKeyToken        '+ManifestReader.MainAssemblyIdentity.publicKeyToken);
                Writeln('');
    
                Writeln('Dependent Assembly Identity');
                Writeln('---------------------------');
                Writeln('type     '+ManifestReader.DependentAssembly.&type);
                Writeln('name     '+ManifestReader.DependentAssembly.name);
                Writeln('language '+ManifestReader.DependentAssembly.language);
                Writeln('version  '+ManifestReader.DependentAssembly.version);
                Writeln('processorArchitecture '+ManifestReader.DependentAssembly.processorArchitecture);
                Writeln('publicKeyToken        '+ManifestReader.DependentAssembly.publicKeyToken);
                Writeln('');
    
                Writeln('Requested Execution Level');
                Writeln('---------------------------');
                Writeln('level     '+ManifestReader.RequestedExecutionLevel.level);
                Writeln('uiAccess  '+ManifestReader.RequestedExecutionLevel.uiAccess);
    
              finally
                ManifestReader.Free;
              end;
            finally
              CoUninitialize;
            end;
         except
            on E:Exception do
                Writeln(E.Classname, ':', E.Message);
         end;
          Readln;
        end.
    

    【讨论】:

    • 非常有用的一段代码!但是,仅当清单 xml 未以删除编译器信息的方式更改时才有效(在我的情况下)。无论如何,谢谢你!
    • @MarioVermeulen,如果代码不是您的或在文章中找到,您必须注明原作者。原创文章How get and parse a manifest of an external application using delphi
    • 这段代码应该用什么版本的Delphi编译?不能在 D7 中编译,使用 XE10.2 生成的输出看起来像标题但没有数据。
    猜你喜欢
    • 2011-04-05
    • 2012-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-11
    相关资源
    最近更新 更多