【问题标题】:How to find if a native DLL file is compiled as x64 or x86?如何查找本机 DLL 文件是编译为 x64 还是 x86?
【发布时间】:2010-10-03 14:25:57
【问题描述】:

我想确定本机程序集是从托管代码应用程序 (C#) 编译为 x64 还是 x86。

我认为它必须在 PE 标头中的某个位置,因为操作系统加载程序需要知道此信息,但我找不到它。当然我更喜欢在托管代码中做,但如果有必要,我可以使用原生 C++。

【问题讨论】:

标签: c# .net winapi 64-bit x86-64


【解决方案1】:

显然您可以在可移植可执行文件的标头中找到它。 corflags.exe 实用程序能够显示它是否针对 x64。希望这可以帮助您找到有关它的更多信息。

【讨论】:

  • 感谢 Steven,但 corflags.exe 不适用于本机程序集。
  • Windows 10:>corflags libzmq.dll \n\n ... corflags : error CF008 : The specified file does not have a valid managed header
【解决方案2】:

64 位二进制文​​件以 PE32+ 格式存储。试试看http://www.masm32.com/board/index.php?action=dlattach;topic=6687.0;id=3486

【讨论】:

    【解决方案3】:

    对于非托管 DLL 文件,您需要先检查它是否是 16 位 DLL 文件(希望不是)。 然后检查IMAGE\_FILE_HEADER.Machine 字段。

    Someone else 已经花时间解决了这个问题,所以我在这里重复一下:

    要区分 32 位和 64 位 PE 文件,您应该检查 IMAGE_FILE_HEADER.Machine 字段。基于 Microsoft PE 和 COFF 下面的规格,我已经列出了 该字段的所有可能值: http://download.microsoft.com/download/9/c/5/9c5b2167-8017-4bae-9fde-d599bac8184a/pecoff_v8.doc

    IMAGE_FILE_MACHINE_UNKNOWN 0x0 该字段的内容假定适用于任何机器类型

    IMAGE_FILE_MACHINE_AM33 0x1d3 松下 AM33

    IMAGE_FILE_MACHINE_AMD64 0x8664 x64

    IMAGE_FILE_MACHINE_ARM 0x1c0 ARM 小端序

    IMAGE_FILE_MACHINE_EBC 0xebc EFI 字节码

    IMAGE_FILE_MACHINE_I386 0x14c Intel 386 或更高版本的处理器和兼容的处理器

    IMAGE_FILE_MACHINE_IA64 0x200 Intel Itanium 处理器家族

    IMAGE_FILE_MACHINE_M32R 0x9041 三菱 M32R 小端序

    IMAGE_FILE_MACHINE_MIPS16 0x266 MIPS16

    IMAGE_FILE_MACHINE_MIPSFPU 0x366 MIPS 与 FPU

    IMAGE_FILE_MACHINE_MIPSFPU16 0x466 MIPS16 with FPU

    IMAGE_FILE_MACHINE_POWERPC 0x1f0 Power PC 小端序

    IMAGE_FILE_MACHINE_POWERPCFP 0x1f1 支持浮点的Power PC

    IMAGE_FILE_MACHINE_R4000 0x166 MIPS 小端序

    IMAGE_FILE_MACHINE_SH3 0x1a2 日立 SH3

    IMAGE_FILE_MACHINE_SH3DSP 0x1a3 日立 SH3 DSP

    IMAGE_FILE_MACHINE_SH4 0x1a6 日立 SH4

    IMAGE_FILE_MACHINE_SH5 0x1a8 日立 SH5

    IMAGE_FILE_MACHINE_THUMB 0x1c2 拇指

    IMAGE_FILE_MACHINE_WCEMIPSV2 0x169 MIPS little-endian WCE v2

    是的,您可以查看 IMAGE_FILE_MACHINE_AMD64|IMAGE_FILE_MACHINE_IA64 用于 64 位,IMAGE_FILE_MACHINE_I386 用于 32 位。

    【讨论】:

    • 你的第二个链接失效了:s
    【解决方案4】:

    您可以找到C# sample implementation hereIMAGE_FILE_HEADER 解决方案

    【讨论】:

      【解决方案5】:

      CorFlags 有一个简单的方法可以做到这一点。打开 Visual Studio 命令提示符并键入“corflags [您的程序集]”。你会得到这样的东西:

      c:\Program Files (x86)\Microsoft Visual Studio 9.0\VC>corflags "C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Data.dll"

      Microsoft (R) .NET Framework CorFlags 转换工具。版本 3.5.21022.8 版权所有 (c) 微软公司。 保留所有权利。

      版本:v2.0.50727 CLR 标头:2.5 聚乙烯:PE32 CorFlags : 24 仅 : 0 32位:0 签名:1

      您正在专门研究 PE 和 32BIT。

      • 任何 CPU

        PE:PE32
        32位:0

      • x86

        PE:PE32
        32位:1

      • x64:

        PE:PE32+
        32位:0

      【讨论】:

      • @BLogan 你应该看看我上面对 Steven Behnke 的评论。我知道 corflags 实用程序,但它不适用于本机程序集。
      • Corflags 输出在后续版本(Windows SDK 8 或更高版本)中发生了变化。现在它有 32BITREQUIRED 和 32BITPREFERRED 而不是 32BIT。请参阅位于 C:\Program Files (x86)\Windows Kits\8.0\Include\um\CorHdr.h 的 CorHdr.h 中的说明。据我所知,32BITREQUIRED 取代了 32BIT。另请参阅此question 的答案。
      【解决方案6】:

      您也可以使用DUMPBIN。使用/headers/all 标志及其列出的第一个文件头。

      dumpbin /headers cv210.dll
      

      64 位

      Microsoft (R) COFF/PE Dumper Version 10.00.30319.01
      Copyright (C) Microsoft Corporation.  All rights reserved.
      
      
      Dump of file cv210.dll
      
      PE signature found
      
      File Type: DLL
      
      FILE HEADER VALUES
                  8664 machine (x64)
                     6 number of sections
              4BBAB813 time date stamp Tue Apr 06 12:26:59 2010
                     0 file pointer to symbol table
                     0 number of symbols
                    F0 size of optional header
                  2022 characteristics
                         Executable
                         Application can handle large (>2GB) addresses
                         DLL
      

      32 位

      Microsoft (R) COFF/PE Dumper Version 10.00.30319.01
      Copyright (C) Microsoft Corporation.  All rights reserved.
      
      
      Dump of file acrdlg.dll
      
      PE signature found
      
      File Type: DLL
      
      FILE HEADER VALUES
                   14C machine (x86)
                     5 number of sections
              467AFDD2 time date stamp Fri Jun 22 06:38:10 2007
                     0 file pointer to symbol table
                     0 number of symbols
                    E0 size of optional header
                  2306 characteristics
                         Executable
                         Line numbers stripped
                         32 bit word machine
                         Debug information stripped
                         DLL
      

      “查找”可以让生活稍微轻松一些:

      dumpbin /headers cv210.dll |find "machine"
              8664 machine (x64)
      

      【讨论】:

      • 对用户更友好 ;)
      • DUMPBIN 不适用于 .NET EXE。我有一个 64 位 .NET EXE,DUMPBIN 说它是 32 位(“14C 机器(x86)”),但 corflags 说是任何 CPU(“PE:PE32,32BIT:0”)。 Dependency Walker 也误诊了它。
      • 需要mspdb100.dll:(
      • @Altaveron 我遇到了同样的问题,但是通过将 DLL 文件 mspdb100.dll 复制到 dumpbin.exe 所在的文件夹来解决它。 DUMPBIN 可以在那之后运行。对我来说,EXE 位于 <Visual Studio Install folder>\VC\bin,DLL 位于 <Visual Studio Install folder>\Common7\IDE
      • 安装了 Visual Studio 的用户可以从 Visual Studio 命令提示符处获得 DUMPBIN
      【解决方案7】:

      IMAGE_OPTIONAL_HEADERMagic 字段(尽管 Windows 可执行映像(DLL/EXE 文件)中的标头没有任何可选内容)将告诉您 PE 的体系结构。

      这是从文件中获取架构的示例。

      public static ushort GetImageArchitecture(string filepath) {
          using (var stream = new System.IO.FileStream(filepath, System.IO.FileMode.Open, System.IO.FileAccess.Read))
          using (var reader = new System.IO.BinaryReader(stream)) {
              //check the MZ signature to ensure it's a valid Portable Executable image
              if (reader.ReadUInt16() != 23117) 
                  throw new BadImageFormatException("Not a valid Portable Executable image", filepath);
      
              // seek to, and read, e_lfanew then advance the stream to there (start of NT header)
              stream.Seek(0x3A, System.IO.SeekOrigin.Current); 
              stream.Seek(reader.ReadUInt32(), System.IO.SeekOrigin.Begin);
      
              // Ensure the NT header is valid by checking the "PE\0\0" signature
              if (reader.ReadUInt32() != 17744)
                  throw new BadImageFormatException("Not a valid Portable Executable image", filepath);
      
              // seek past the file header, then read the magic number from the optional header
              stream.Seek(20, System.IO.SeekOrigin.Current); 
              return reader.ReadUInt16();
          }
      }
      

      目前仅有的两个架构常量是:

      0x10b - PE32
      0x20b - PE32+
      

      干杯

      更新 自从我发布这个答案已经有一段时间了,但我仍然看到它不时地得到一些支持,所以我认为它值得更新。我写了一种方法来获取Portable Executable 图像的架构,它还检查它是否被编译为AnyCPU。不幸的是,答案在 C++ 中,但如果您有几分钟的时间查看 WinNT.h 中的结构,移植到 C# 应该不会太难。如果人们有兴趣,我会用 C# 编写一个端口,但除非人们真的想要它,否则我不会花太多时间去强调它。

      #include <Windows.h>
      
      #define MKPTR(p1,p2) ((DWORD_PTR)(p1) + (DWORD_PTR)(p2))
      
      typedef enum _pe_architecture {
          PE_ARCHITECTURE_UNKNOWN = 0x0000,
          PE_ARCHITECTURE_ANYCPU  = 0x0001,
          PE_ARCHITECTURE_X86     = 0x010B,
          PE_ARCHITECTURE_x64     = 0x020B
      } PE_ARCHITECTURE;
      
      LPVOID GetOffsetFromRva(IMAGE_DOS_HEADER *pDos, IMAGE_NT_HEADERS *pNt, DWORD rva) {
          IMAGE_SECTION_HEADER *pSecHd = IMAGE_FIRST_SECTION(pNt);
          for(unsigned long i = 0; i < pNt->FileHeader.NumberOfSections; ++i, ++pSecHd) {
              // Lookup which section contains this RVA so we can translate the VA to a file offset
              if (rva >= pSecHd->VirtualAddress && rva < (pSecHd->VirtualAddress + pSecHd->Misc.VirtualSize)) {
                  DWORD delta = pSecHd->VirtualAddress - pSecHd->PointerToRawData;
                  return (LPVOID)MKPTR(pDos, rva - delta);
              }
          }
          return NULL;
      }
      
      PE_ARCHITECTURE GetImageArchitecture(void *pImageBase) {
          // Parse and validate the DOS header
          IMAGE_DOS_HEADER *pDosHd = (IMAGE_DOS_HEADER*)pImageBase;
          if (IsBadReadPtr(pDosHd, sizeof(pDosHd->e_magic)) || pDosHd->e_magic != IMAGE_DOS_SIGNATURE)
              return PE_ARCHITECTURE_UNKNOWN;
      
          // Parse and validate the NT header
          IMAGE_NT_HEADERS *pNtHd = (IMAGE_NT_HEADERS*)MKPTR(pDosHd, pDosHd->e_lfanew);
          if (IsBadReadPtr(pNtHd, sizeof(pNtHd->Signature)) || pNtHd->Signature != IMAGE_NT_SIGNATURE)
              return PE_ARCHITECTURE_UNKNOWN;
      
          // First, naive, check based on the 'Magic' number in the Optional Header.
          PE_ARCHITECTURE architecture = (PE_ARCHITECTURE)pNtHd->OptionalHeader.Magic;
      
          // If the architecture is x86, there is still a possibility that the image is 'AnyCPU'
          if (architecture == PE_ARCHITECTURE_X86) {
              IMAGE_DATA_DIRECTORY comDirectory = pNtHd->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR];
              if (comDirectory.Size) {
                  IMAGE_COR20_HEADER *pClrHd = (IMAGE_COR20_HEADER*)GetOffsetFromRva(pDosHd, pNtHd, comDirectory.VirtualAddress);
                  // Check to see if the CLR header contains the 32BITONLY flag, if not then the image is actually AnyCpu
                  if ((pClrHd->Flags & COMIMAGE_FLAGS_32BITREQUIRED) == 0)
                      architecture = PE_ARCHITECTURE_ANYCPU;
              }
          }
      
          return architecture;
      }
      

      该函数接受一个指向内存中 PE 映像的指针(因此您可以选择如何获取它们的毒药;内存映射或将整个内容读入内存......随便)。

      【讨论】:

      • 非常有趣,但是当我使用 Any CPU 编译应用程序时,结果是 0x10B。这是错误的,因为我的应用程序在 x64 系统中运行。还有其他标志要检查吗?
      • AnyCPU 的意思就是:AnyCPU,因此它在 PE 标头中列为 0x10B 以向后兼容 32 位。要检查它与直接 32 位之间的区别,您需要找出 CorFlags 在 PE 中从何处获取其 32BIT 标志,我不知道是什么。
      • @JasonLarke 我确实是通过谷歌搜索来到这里的,你的代码 sn-p 帮助了我。非常感谢!
      • @Samuel 更新以检查 AnyCPU 标志。
      • 检查 32 位程序集时,C# 代码在 64 位进程中工作吗?例如,Module.GetPEKind msdn.microsoft.com/en-us/library/… 失败
      【解决方案8】:

      使用十六进制编辑器打开 dll,例如 HxD

      如果第 9 行有“dt”,则为 64 位。

      如果有“L”。第 9 行是 32 位。

      【讨论】:

      • 找不到“dt”和“L”。在“Far Manager”十六进制查看器上。
      • 显示为 d。和L。
      【解决方案9】:

      我在 powershell 脚本的第一个答案中重写了 c++ solution。脚本可以确定这种类型的 .exe 和 .dll 文件:

      #Description       C# compiler switch             PE type       machine corflags
      #MSIL              /platform:anycpu (default)     PE32  x86     ILONLY
      #MSIL 32 bit pref  /platform:anycpu32bitpreferred PE32  x86     ILONLY | 32BITREQUIRED | 32BITPREFERRED
      #x86 managed       /platform:x86                  PE32  x86     ILONLY | 32BITREQUIRED
      #x86 mixed         n/a                            PE32  x86     32BITREQUIRED
      #x64 managed       /platform:x64                  PE32+ x64     ILONLY
      #x64 mixed         n/a                            PE32+ x64  
      #ARM managed       /platform:arm                  PE32  ARM     ILONLY
      #ARM mixed         n/a                            PE32  ARM  
      

      与 corflags.exe 和通过 C# 中的 Assembly.Load 加载程序集相比,此解决方案具有一些优势 - 您永远不会收到 BadImageFormatException 或有关无效标头的消息。

      function GetActualAddressFromRVA($st, $sec, $numOfSec, $dwRVA)
      {
          [System.UInt32] $dwRet = 0;
          for($j = 0; $j -lt $numOfSec; $j++)   
          {   
              $nextSectionOffset = $sec + 40*$j;
              $VirtualSizeOffset = 8;
              $VirtualAddressOffset = 12;
              $SizeOfRawDataOffset = 16;
              $PointerToRawDataOffset = 20;
      
          $Null = @(
              $curr_offset = $st.BaseStream.Seek($nextSectionOffset + $VirtualSizeOffset, [System.IO.SeekOrigin]::Begin);        
              [System.UInt32] $VirtualSize = $b.ReadUInt32();
              [System.UInt32] $VirtualAddress = $b.ReadUInt32();
              [System.UInt32] $SizeOfRawData = $b.ReadUInt32();
              [System.UInt32] $PointerToRawData = $b.ReadUInt32();        
      
              if ($dwRVA -ge $VirtualAddress -and $dwRVA -lt ($VirtualAddress + $VirtualSize)) {
                  $delta = $VirtualAddress - $PointerToRawData;
                  $dwRet = $dwRVA - $delta;
                  return $dwRet;
              }
              );
          }
          return $dwRet;
      }
      
      function Get-Bitness2([System.String]$path, $showLog = $false)
      {
          $Obj = @{};
          $Obj.Result = '';
          $Obj.Error = $false;
      
          $Obj.Log = @(Split-Path -Path $path -Leaf -Resolve);
      
          $b = new-object System.IO.BinaryReader([System.IO.File]::Open($path,[System.IO.FileMode]::Open,[System.IO.FileAccess]::Read, [System.IO.FileShare]::Read));
          $curr_offset = $b.BaseStream.Seek(0x3c, [System.IO.SeekOrigin]::Begin)
          [System.Int32] $peOffset = $b.ReadInt32();
          $Obj.Log += 'peOffset ' + "{0:X0}" -f $peOffset;
      
          $curr_offset = $b.BaseStream.Seek($peOffset, [System.IO.SeekOrigin]::Begin);
          [System.UInt32] $peHead = $b.ReadUInt32();
      
          if ($peHead -ne 0x00004550) {
              $Obj.Error = $true;
              $Obj.Result = 'Bad Image Format';
              $Obj.Log += 'cannot determine file type (not x64/x86/ARM) - exit with error';
          };
      
          if ($Obj.Error)
          {
              $b.Close();
              Write-Host ($Obj.Log | Format-List | Out-String);
              return $false;
          };
      
          [System.UInt16] $machineType = $b.ReadUInt16();
          $Obj.Log += 'machineType ' + "{0:X0}" -f $machineType;
      
          [System.UInt16] $numOfSections = $b.ReadUInt16();
          $Obj.Log += 'numOfSections ' + "{0:X0}" -f $numOfSections;
          if (($machineType -eq 0x8664) -or ($machineType -eq 0x200)) { $Obj.Log += 'machineType: x64'; }
          elseif ($machineType -eq 0x14c)                             { $Obj.Log += 'machineType: x86'; }
          elseif ($machineType -eq 0x1c0)                             { $Obj.Log += 'machineType: ARM'; }
          else{
              $Obj.Error = $true;
              $Obj.Log += 'cannot determine file type (not x64/x86/ARM) - exit with error';
          };
      
          if ($Obj.Error) {
              $b.Close();
              Write-Output ($Obj.Log | Format-List | Out-String);
              return $false;
          };
      
          $curr_offset = $b.BaseStream.Seek($peOffset+20, [System.IO.SeekOrigin]::Begin);
          [System.UInt16] $sizeOfPeHeader = $b.ReadUInt16();
      
          $coffOffset = $peOffset + 24;#PE header size is 24 bytes
          $Obj.Log += 'coffOffset ' + "{0:X0}" -f $coffOffset;
      
          $curr_offset = $b.BaseStream.Seek($coffOffset, [System.IO.SeekOrigin]::Begin);#+24 byte magic number
          [System.UInt16] $pe32 = $b.ReadUInt16();         
          $clr20headerOffset = 0;
          $flag32bit = $false;
          $Obj.Log += 'pe32 magic number: ' + "{0:X0}" -f $pe32;
          $Obj.Log += 'size of optional header ' + ("{0:D0}" -f $sizeOfPeHeader) + " bytes";
      
          #COMIMAGE_FLAGS_ILONLY               =0x00000001,
          #COMIMAGE_FLAGS_32BITREQUIRED        =0x00000002,
          #COMIMAGE_FLAGS_IL_LIBRARY           =0x00000004,
          #COMIMAGE_FLAGS_STRONGNAMESIGNED     =0x00000008,
          #COMIMAGE_FLAGS_NATIVE_ENTRYPOINT    =0x00000010,
          #COMIMAGE_FLAGS_TRACKDEBUGDATA       =0x00010000,
          #COMIMAGE_FLAGS_32BITPREFERRED       =0x00020000,
      
          $COMIMAGE_FLAGS_ILONLY        = 0x00000001;
          $COMIMAGE_FLAGS_32BITREQUIRED = 0x00000002;
          $COMIMAGE_FLAGS_32BITPREFERRED = 0x00020000;
      
          $offset = 96;
          if ($pe32 -eq 0x20b) {
              $offset = 112;#size of COFF header is bigger for pe32+
          }     
      
          $clr20dirHeaderOffset = $coffOffset + $offset + 14*8;#clr directory header offset + start of section number 15 (each section is 8 byte long);
          $Obj.Log += 'clr20dirHeaderOffset ' + "{0:X0}" -f $clr20dirHeaderOffset;
          $curr_offset = $b.BaseStream.Seek($clr20dirHeaderOffset, [System.IO.SeekOrigin]::Begin);
          [System.UInt32] $clr20VirtualAddress = $b.ReadUInt32();
          [System.UInt32] $clr20Size = $b.ReadUInt32();
          $Obj.Log += 'clr20VirtualAddress ' + "{0:X0}" -f $clr20VirtualAddress;
          $Obj.Log += 'clr20SectionSize ' + ("{0:D0}" -f $clr20Size) + " bytes";
      
          if ($clr20Size -eq 0) {
              if ($machineType -eq 0x1c0) { $Obj.Result = 'ARM native'; }
              elseif ($pe32 -eq 0x10b)    { $Obj.Result = '32-bit native'; }
              elseif($pe32 -eq 0x20b)     { $Obj.Result = '64-bit native'; }
      
             $b.Close();   
             if ($Obj.Result -eq '') { 
                  $Obj.Error = $true;
                  $Obj.Log += 'Unknown type of file';
             }
             else { 
                  if ($showLog) { Write-Output ($Obj.Log | Format-List | Out-String); };
                  return $Obj.Result;
             }
          };
      
          if ($Obj.Error) {
              $b.Close();
              Write-Host ($Obj.Log | Format-List | Out-String);
              return $false;
          };
      
          [System.UInt32]$sectionsOffset = $coffOffset + $sizeOfPeHeader;
          $Obj.Log += 'sectionsOffset ' + "{0:X0}" -f $sectionsOffset;
          $realOffset = GetActualAddressFromRVA $b $sectionsOffset $numOfSections $clr20VirtualAddress;
          $Obj.Log += 'real IMAGE_COR20_HEADER offset ' + "{0:X0}" -f $realOffset;
          if ($realOffset -eq 0) {
              $Obj.Error = $true;
              $Obj.Log += 'cannot find COR20 header - exit with error';
              $b.Close();
              return $false;
          };
      
          if ($Obj.Error) {
              $b.Close();
              Write-Host ($Obj.Log | Format-List | Out-String);
              return $false;
          };
      
          $curr_offset = $b.BaseStream.Seek($realOffset + 4, [System.IO.SeekOrigin]::Begin);
          [System.UInt16] $majorVer = $b.ReadUInt16();
          [System.UInt16] $minorVer = $b.ReadUInt16();
          $Obj.Log += 'IMAGE_COR20_HEADER version ' + ("{0:D0}" -f $majorVer) + "." + ("{0:D0}" -f $minorVer);
      
          $flagsOffset = 16;#+16 bytes - flags field
          $curr_offset = $b.BaseStream.Seek($realOffset + $flagsOffset, [System.IO.SeekOrigin]::Begin);
          [System.UInt32] $flag32bit = $b.ReadUInt32();
          $Obj.Log += 'CorFlags: ' + ("{0:X0}" -f $flag32bit);
      
      #Description       C# compiler switch             PE type       machine corflags
      #MSIL              /platform:anycpu (default)     PE32  x86     ILONLY
      #MSIL 32 bit pref  /platform:anycpu32bitpreferred PE32  x86     ILONLY | 32BITREQUIRED | 32BITPREFERRED
      #x86 managed       /platform:x86                  PE32  x86     ILONLY | 32BITREQUIRED
      #x86 mixed         n/a                            PE32  x86     32BITREQUIRED
      #x64 managed       /platform:x64                  PE32+ x64     ILONLY
      #x64 mixed         n/a                            PE32+ x64  
      #ARM managed       /platform:arm                  PE32  ARM     ILONLY
      #ARM mixed         n/a                            PE32  ARM  
      
          $isILOnly = ($flag32bit -band $COMIMAGE_FLAGS_ILONLY) -eq $COMIMAGE_FLAGS_ILONLY;
          $Obj.Log += 'ILONLY: ' + $isILOnly;
          if ($machineType -eq 0x1c0) {#if ARM
              if ($isILOnly) { $Obj.Result = 'ARM managed'; } 
                        else { $Obj.Result = 'ARM mixed'; }
          }
          elseif ($pe32 -eq 0x10b) {#pe32
              $is32bitRequired = ($flag32bit -band $COMIMAGE_FLAGS_32BITREQUIRED) -eq $COMIMAGE_FLAGS_32BITREQUIRED;
              $is32bitPreffered = ($flag32bit -band $COMIMAGE_FLAGS_32BITPREFERRED) -eq $COMIMAGE_FLAGS_32BITPREFERRED;
              $Obj.Log += '32BIT: ' + $is32bitRequired;    
              $Obj.Log += '32BIT PREFFERED: ' + $is32bitPreffered 
              if     ($is32bitRequired  -and $isILOnly  -and $is32bitPreffered) { $Obj.Result = 'AnyCpu 32bit-preffered'; }
              elseif ($is32bitRequired  -and $isILOnly  -and !$is32bitPreffered){ $Obj.Result = 'x86 managed'; }
              elseif (!$is32bitRequired -and !$isILOnly -and $is32bitPreffered) { $Obj.Result = 'x86 mixed'; }
              elseif ($isILOnly)                                                { $Obj.Result = 'AnyCpu'; }
         }
         elseif ($pe32 -eq 0x20b) {#pe32+
              if ($isILOnly) { $Obj.Result = 'x64 managed'; } 
                        else { $Obj.Result = 'x64 mixed'; }
         }
      
         $b.Close();   
         if ($showLog) { Write-Host ($Obj.Log | Format-List | Out-String); }
         if ($Obj.Result -eq ''){ return 'Unknown type of file';};
         $flags = '';
         if ($isILOnly) {$flags += 'ILONLY';}
         if ($is32bitRequired) {
              if ($flags -ne '') {$flags += ' | ';}
              $flags += '32BITREQUIRED';
         }
         if ($is32bitPreffered) {
              if ($flags -ne '') {$flags += ' | ';}
              $flags += '32BITPREFERRED';
         }
         if ($flags -ne '') {$flags = ' (' + $flags +')';}
         return $Obj.Result + $flags;
      }
      

      用法示例:

      #$filePath = "C:\Windows\SysWOW64\regedit.exe";#32 bit native on 64bit windows
      $filePath = "C:\Windows\regedit.exe";#64 bit native on 64bit windows | should be 32 bit native on 32bit windows
      
      Get-Bitness2 $filePath $true;
      

      如果不需要看细节,可以省略第二个参数

      【讨论】:

        【解决方案10】:

        这里描述了一种快速且可能很脏的方法:https://superuser.com/a/889267。您在编辑器中打开 DLL 并检查“PE”序列之后的第一个字符。

        【讨论】:

          【解决方案11】:

          这个trick 工作并且只需要记事本。

          使用文本编辑器(如记事本)打开 dll 文件并找到字符串 PE 的第一个匹配项。以下字符定义 dll 是 32 位还是 64 位。

          32 位:

          PE  L
          

          64 位:

          PE  d†
          

          【讨论】:

            【解决方案12】:

            由于第三方工具总是安装在%Program files (x86)% 中(即使是 x64 安装!)并且需要适当的 x32|x64 fortran 运行时首先在%path% 上列出才能正确运行,所以我收集了c++ 和@ 987654322@解到matlab中返回:

            • 亲切Executable|Library|Other
            • 代码类型Native|Mixed|Managed
            • 平台x32|x64|AnyCpu|x32Preferred|Other

            一旦内存中有原始 PE 结构,应该很容易适应其他语言。

            function [simplifiedInfo] = GetPortableExecutableSimplifiedInfo(filename)
            %[
                % Checking arguments
                if (nargin <1), error('MATLAB:minrhs', 'Not enough input argments.'); end
            
                % Initializing simplified info    
                simplifiedInfo.Kind = 'Other';
                simplifiedInfo.CodeType = 'Other';
                simplifiedInfo.Platform = 'Other';
            
                % Obtaining raw info
                [rawInfo, PEConstants] = GetPortableExecutableRawInfo(filename);
            
                % Determining 'Kind' of PE
                if (isfield(rawInfo, 'PEOptionalHeader') && (rawInfo.COFFHeader.Characteristics.IMAGE_FILE_EXECUTABLE_IMAGE))
                    if (rawInfo.COFFHeader.Characteristics.IMAGE_FILE_DLL)
                        simplifiedInfo.Kind = 'Library';
                    else
                        simplifiedInfo.Kind = 'Executable';
                    end
                else
                    % No optional header or no IMAGE_FILE_EXECUTABLE_IMAGE flag ... 
                    % Maybe just .obj or other thing
                    simplifiedInfo.Kind = 'Other';
                end
            
                % Determining 'CodeType'
                % NB: 'COR20Header' is present for MSIL code, but not for native code
                if (isfield(rawInfo, 'COR20Header'))
                    if (rawInfo.COR20Header.Flags.COMIMAGE_FLAGS_ILONLY)
                        simplifiedInfo.CodeType = 'Managed';
                    else
                        simplifiedInfo.CodeType = 'Mixed';
                    end
                else
                    simplifiedInfo.CodeType = 'Native';
                end
            
                % Determining platform
                if (rawInfo.COFFHeader.Machine == PEConstants.IMAGE_FILE_MACHINE_AMD64)
                    simplifiedInfo.Platform = 'x64';
                elseif (rawInfo.COFFHeader.Machine == PEConstants.IMAGE_FILE_MACHINE_I386)
                    if (isfield(rawInfo, 'COR20Header'))
                        % PE contains MSIL code, need more checks
                        if (rawInfo.COR20Header.Flags.COMIMAGE_FLAGS_32BITREQUIRED)
                            if (rawInfo.COR20Header.Flags.COMIMAGE_FLAGS_32BITPREFERRED)
                                simplifiedInfo.Platform = 'x32Preferred';
                            else
                                simplifiedInfo.Platform = 'x32';
                            end
                        else
                            simplifiedInfo.Platform = 'AnyCpu';
                        end
                    else
                        % This is native code so ...
                        simplifiedInfo.Platform = 'x32';
                    end
                else
                    % ARM, ...
                    simplifiedInfo.Platform = 'Other';
                end
            %]
            end
            

            内部GetPortableExecutableRawInfo函数源代码可在here获取。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2019-04-02
              • 1970-01-01
              • 2019-12-30
              • 2011-12-03
              • 1970-01-01
              • 1970-01-01
              • 2012-03-17
              • 1970-01-01
              相关资源
              最近更新 更多