如何确定.NET程序集是为x86还是x64构建的?

我有一个.NET程序集的任意列表。

我需要以编程方式检查每个DLL是否为x86构建(而不是x64或任何CPU)。 这可能吗?

看看System.Reflection.AssemblyName.GetAssemblyName(string assemblyFile)

您可以从返回的AssemblyName实例中检查程序集元数据:

使用PowerShell

 [36] C:\> [reflection.assemblyname] :: GetAssemblyName(“$ {pwd} \ Microsoft.GLEE.dll”)|  FL

名称:Microsoft.GLEE
版本:1.0.0.0
企业文化
 CodeBase:file:/// C:/ projects / powershell / BuildAnalyzer / ...
 EscapedCodeBase:file:/// C:/ projects / powershell / BuildAnalyzer / ...
 ProcessorArchitecture:MSIL
标志:PublicKey
 HashAlgorithm:SHA1
版本兼容性:SameMachine
 KeyPair:
 FullName:Microsoft.GLEE,Version = 1.0.0.0,Culture = neut ... 

在这里, ProcessorArchitecture识别目标平台。

我在这个例子中使用PowerShell来调用这个方法。

您可以使用CorFlags CLI工具(例如,C:\ Program Files \ Microsoft SDKs \ Windows \ v7.0 \ Bin \ CorFlags.exe)来确定程序集的状态,并根据其输出结果打开程序集二进制资产,您应该能够确定您需要寻找的位置,以确定32BIT标志是否设置为1( x86 )或0( 任何CPUx64 ,取决于PE ):

 Option | PE | 32BIT ----------|-------|--------- x86 | PE32 | 1 Any CPU | PE32 | 0 x64 | PE32+ | 0 

用.NET开发的博客帖子x64有一些关于corflags信息。

更好的是,您可以使用Module.GetPEKind来确定程序集是否为PortableExecutableKindsPE32Plus (64位), Required32Bit (32位和WOW)或ILOnly (任何CPU)以及其他属性。

只是澄清,CorFlags.exe是.NET Framework SDK的一部分 。 我的机器上有开发工具,而确定一个DLL是否只有32位的最简单方法是:

  1. 打开Visual Studio命令提示符(在Windows中:菜单开始/程序/ Microsoft Visual Studio / Visual Studio工具/ Visual Studio 2008命令提示符)

  2. CD到包含有问题的DLL的目录

  3. 像这样运行corflags:corflags MyAssembly.dll

你会得到这样的输出:

  Microsoft (R) .NET Framework CorFlags Conversion Tool. Version 3.5.21022.8 Copyright (c) Microsoft Corporation. All rights reserved. Version : v2.0.50727 CLR Header: 2.5 PE : PE32 CorFlags : 3 ILONLY : 1 32BIT : 1 Signed : 0 

根据意见,上面的标志应被读作如下:

  • 任何CPU:PE = PE32和32BIT = 0
  • x86:PE = PE32和32BIT = 1
  • 64位:PE = PE32 +和32BIT = 0

你怎么写你自己的? 自从在Windows 95中实现以来,PE体系结构的核心没有被严重改变。下面是一个C#的例子:

  public static ushort GetPEArchitecture(string pFilePath) { ushort architecture = 0; try { using (System.IO.FileStream fStream = new System.IO.FileStream(pFilePath, System.IO.FileMode.Open, System.IO.FileAccess.Read)) { using (System.IO.BinaryReader bReader = new System.IO.BinaryReader(fStream)) { if (bReader.ReadUInt16() == 23117) //check the MZ signature { fStream.Seek(0x3A, System.IO.SeekOrigin.Current); //seek to e_lfanew. fStream.Seek(bReader.ReadUInt32(), System.IO.SeekOrigin.Begin); //seek to the start of the NT header. if (bReader.ReadUInt32() == 17744) //check the PE\0\0 signature. { fStream.Seek(20, System.IO.SeekOrigin.Current); //seek past the file header, architecture = bReader.ReadUInt16(); //read the magic number of the optional header. } } } } } catch (Exception) { /* TODO: Any exception handling you want to do, personally I just take 0 as a sign of failure */} //if architecture returns 0, there has been an error. return architecture; } } 

现在的常量是:

 0x10B - PE32 format. 0x20B - PE32+ format. 

但是通过这种方法,它允许使用新常量的可能性,只要验证您认为合适的回报即可。

尝试从CodePlex的这个项目中使用CorFlagsReader。 它没有引用其他程序集,可以按原样使用。

 [TestMethod] public void EnsureKWLLibrariesAreAll64Bit() { var assemblies = Assembly.GetExecutingAssembly().GetReferencedAssemblies().Where(x => x.FullName.StartsWith("YourCommonProjectName")).ToArray(); foreach (var assembly in assemblies) { var myAssemblyName = AssemblyName.GetAssemblyName(assembly.FullName.Split(',')[0] + ".dll"); Assert.AreEqual(ProcessorArchitecture.MSIL, myAssemblyName.ProcessorArchitecture); } } 

下面是一个批处理文件,它将对当前工作目录和所有子目录中的所有dllsexes运行corflags.exe ,解析结果并显示每个目录的目标体系结构。

根据所使用的corflags.exe的版本,输出中的行项目将包含32BIT 32BITREQ (和32BITPREF )。 输出中包含这两者中的哪一个是必须检查以区分Any CPUx86的关键行项目。 如果您使用的是早期版本的corflags.exe (在Windows SDK v8.0A之前版本),则只有32BIT订单项出现在输出中,正如其他人在过去的回答中指出的那样。 否则32BITREQ32BITPREF取代它。

这假定corflags.exe%PATH% 。 确保这一点最简单的方法是使用Developer Command Prompt 。 或者,您可以从它的默认位置复制它。

如果下面的批处理文件针对非托管的dllexe ,它将错误地显示为x86 ,因为Corflags.exe的实际输出将是类似于以下错误消息:

corflags:错误CF008:指定的文件没有有效的管理标题

 @echo off echo. echo Target architecture for all exes and dlls: echo. REM For each exe and dll in this directory and all subdirectories... for %%a in (.exe, .dll) do forfiles /s /m *%%a /c "cmd /c echo @relpath" > testfiles.txt for /f %%b in (testfiles.txt) do ( REM Dump corflags results to a text file corflags /nologo %%b > corflagsdeets.txt REM Parse the corflags results to look for key markers findstr /C:"PE32+">nul .\corflagsdeets.txt && ( REM `PE32+` indicates x64 echo %%~b = x64 ) || ( REM pre-v8 Windows SDK listed only "32BIT" line item, REM newer versions list "32BITREQ" and "32BITPREF" line items findstr /C:"32BITREQ : 0">nul /C:"32BIT : 0" .\corflagsdeets.txt && ( REM `PE32` and NOT 32bit required indicates Any CPU echo %%~b = Any CPU ) || ( REM `PE32` and 32bit required indicates x86 echo %%~b = x86 ) ) del corflagsdeets.txt ) del testfiles.txt echo. 

另一种检查.NET程序集目标平台的方法是使用.NET Reflector检查程序集…

@#〜#€〜! 我刚刚意识到新版本不是免费的! 所以,如果你有一个.NET反射器的免费版本,你可以用它来检查目标平台。

cfeduke注意到调用GetPEKind的可能性。 从PowerShell执行此操作可能很有意思。

例如,这里是可以使用的cmdlet的代码: https : //stackoverflow.com/a/16181743/64257

或者,在https://stackoverflow.com/a/4719567/64257注意到“还有PowerShell社区扩展中的Get-PEHeader cmdlet可用于测试可执行映像。

更高级的应用程序,你可以在这里找到: CodePlex – ApiChange

例子:

 C:\Downloads\ApiChange>ApiChange.exe -CorFlags c:\Windows\winhlp32.exe File Name; Type; Size; Processor; IL Only; Signed winhlp32.exe; Unmanaged; 296960; X86 C:\Downloads\ApiChange>ApiChange.exe -CorFlags c:\Windows\HelpPane.exe File Name; Type; Size; Processor; IL Only; Signed HelpPane.exe; Unmanaged; 733696; Amd64 

还有一种方法是从DLL上的Visual Studio工具中使用dumpbin并查找相应的输出

 dumpbin.exe /HEADERS <your dll path> FILE HEADER VALUE 14C machine (x86) 4 number of sections 5885AC36 time date stamp Mon Jan 23 12:39:42 2017 0 file pointer to symbol table 0 number of symbols E0 size of optional header 2102 characteristics Executable 32 bit word machine DLL 

注意:上面的o / p是32位的dll

dumpbin.exe的一个更有用的选项是/ EXPORTS,它会告诉你由dll公开的功能

 dumpbin.exe /EXPORTS <PATH OD THE DLL> 

JetBrians的DotPeek提供了快速简便的方法来查看msil(anycpu),x86,x64 dotPeek