如何确定.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( 任何CPU或x64 ,取决于PE
):
Option | PE | 32BIT ----------|-------|--------- x86 | PE32 | 1 Any CPU | PE32 | 0 x64 | PE32+ | 0
用.NET开发的博客帖子x64有一些关于corflags
信息。
更好的是,您可以使用Module.GetPEKind
来确定程序集是否为PortableExecutableKinds
值PE32Plus
(64位), Required32Bit
(32位和WOW)或ILOnly
(任何CPU)以及其他属性。
只是澄清,CorFlags.exe是.NET Framework SDK的一部分 。 我的机器上有开发工具,而确定一个DLL是否只有32位的最简单方法是:
-
打开Visual Studio命令提示符(在Windows中:菜单开始/程序/ Microsoft Visual Studio / Visual Studio工具/ Visual Studio 2008命令提示符)
-
CD到包含有问题的DLL的目录
-
像这样运行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); } }
下面是一个批处理文件,它将对当前工作目录和所有子目录中的所有dlls
和exes
运行corflags.exe
,解析结果并显示每个目录的目标体系结构。
根据所使用的corflags.exe
的版本,输出中的行项目将包含32BIT
或 32BITREQ
(和32BITPREF
)。 输出中包含这两者中的哪一个是必须检查以区分Any CPU
和x86
的关键行项目。 如果您使用的是早期版本的corflags.exe
(在Windows SDK v8.0A之前版本),则只有32BIT
订单项出现在输出中,正如其他人在过去的回答中指出的那样。 否则32BITREQ
和32BITPREF
取代它。
这假定corflags.exe
在%PATH%
。 确保这一点最简单的方法是使用Developer Command Prompt
。 或者,您可以从它的默认位置复制它。
如果下面的批处理文件针对非托管的dll
或exe
,它将错误地显示为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