我有一个任意的。net程序集列表。
我需要以编程方式检查每个DLL是否为x86构建(而不是x64或任何CPU)。这可能吗?
我有一个任意的。net程序集列表。
我需要以编程方式检查每个DLL是否为x86构建(而不是x64或任何CPU)。这可能吗?
当前回答
检查.NET程序集的目标平台的另一种方法是使用.NET Reflector检查程序集…
@ # ~ #€~ !我刚刚意识到新版本不是免费的!因此,更正一下,如果你有一个。net reflector的免费版本,你可以用它来检查目标平台。
其他回答
检查.NET程序集的目标平台的另一种方法是使用.NET Reflector检查程序集…
@ # ~ #€~ !我刚刚意识到新版本不是免费的!因此,更正一下,如果你有一个。net reflector的免费版本,你可以用它来检查目标平台。
澄清一下,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
一个更通用的方法-使用文件结构来确定位和图像类型:
public static CompilationMode GetCompilationMode(this FileInfo info)
{
if (!info.Exists)
throw new ArgumentException($"{info.FullName} does not exist");
var intPtr = IntPtr.Zero;
try
{
uint unmanagedBufferSize = 4096;
intPtr = Marshal.AllocHGlobal((int)unmanagedBufferSize);
using (var stream = File.Open(info.FullName, FileMode.Open, FileAccess.Read))
{
var bytes = new byte[unmanagedBufferSize];
stream.Read(bytes, 0, bytes.Length);
Marshal.Copy(bytes, 0, intPtr, bytes.Length);
}
// Check DOS header magic number
if (Marshal.ReadInt16(intPtr) != 0x5a4d)
return CompilationMode.Invalid;
// This will get the address for the WinNT header
var ntHeaderAddressOffset = Marshal.ReadInt32(intPtr + 60);
// Check WinNT header signature
var signature = Marshal.ReadInt32(intPtr + ntHeaderAddressOffset);
if (signature != 0x4550)
return CompilationMode.Invalid;
// Determine file bitness by reading magic from IMAGE_OPTIONAL_HEADER
var magic = Marshal.ReadInt16(intPtr + ntHeaderAddressOffset + 24);
var result = CompilationMode.Invalid;
uint clrHeaderSize;
if (magic == 0x10b)
{
clrHeaderSize = (uint)Marshal.ReadInt32(intPtr + ntHeaderAddressOffset + 24 + 208 + 4);
result |= CompilationMode.Bit32;
}
else if (magic == 0x20b)
{
clrHeaderSize = (uint)Marshal.ReadInt32(intPtr + ntHeaderAddressOffset + 24 + 224 + 4);
result |= CompilationMode.Bit64;
}
else return CompilationMode.Invalid;
result |= clrHeaderSize != 0
? CompilationMode.CLR
: CompilationMode.Native;
return result;
}
finally
{
if (intPtr != IntPtr.Zero)
Marshal.FreeHGlobal(intPtr);
}
}
编译模式枚举
[Flags]
public enum CompilationMode
{
Invalid = 0,
Native = 0x1,
CLR = Native << 1,
Bit32 = CLR << 1,
Bit64 = Bit32 << 1
}
源代码和解释在GitHub。
我喜欢ILSpy工具。它不仅显示了架构,还显示了目标框架:
// linq2db, Version=3.0.0.0, Culture=neutral, PublicKeyToken=e41013125f9e410a
// Global type: <Module>
// Architecture: AnyCPU (64-bit preferred)
// Runtime: v4.0.30319
// This assembly is signed with a strong name key.
// This assembly was compiled using the /deterministic option.
// Hash algorithm: SHA1
因此,可以确定它是。net Core 2.1, .NET Framework 4.6或任何其他版本:
查看System.Reflection.AssemblyName。assemblyFile GetAssemblyName(字符串)。
您可以从返回的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 on Windows环境中。 None:未知或未指定的处理器和每字位数的组合。
在本例中,我使用PowerShell来调用该方法。