我有一个任意的.NET程序集列表.
我需要以编程方式检查每个DLL是否是为x86构建的(而不是x64或任何CPU).这可能吗?
看着 System.Reflection.AssemblyName.GetAssemblyName(string assemblyFile)
您可以从返回的AssemblyName实例检查程序集元数据:
使用PowerShell:
[36] C:\> [reflection.assemblyname]::GetAssemblyName("${pwd}\Microsoft.GLEE.dll") | fl Name : Microsoft.GLEE Version : 1.0.0.0 CultureInfo : CodeBase : file:///C:/projects/powershell/BuildAnalyzer/... EscapedCodeBase : file:///C:/projects/powershell/BuildAnalyzer/... ProcessorArchitecture : MSIL Flags : PublicKey HashAlgorithm : SHA1 VersionCompatibility : SameMachine KeyPair : FullName : Microsoft.GLEE, Version=1.0.0.0, Culture=neut...
在这里,ProcessorArchitecture识别目标平台.
Amd64:基于x64架构的64位处理器.
Arm:ARM处理器.
IA64:仅限64位Intel Itanium处理器.
MSIL:关于处理器和每字位数的中性.
X86:32位Intel处理器,可以是64位平台(WOW64)上的本机或Windows环境中的Windows.
无:处理器和每字位数的未知或未指定组合.
我在这个例子中使用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
博客文章x64开发与.NET有一些信息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 .它没有引用其他程序集,它可以按原样使用.
来自JetBrians的DotPeek提供了快速简便的方法来查看msil(anycpu),x86,x64
[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); } }
下面是将运行一个批处理文件,corflags.exe
对所有dlls
与exes
当前工作目录及其所有子目录,解析结果,并显示每个目标架构。
取决于版本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.