X86 :32位Intel处理器,可以是64位平台(WOW64)上的本机或Windows环境中的Windows .
None :处理器和每字位数的未知或未指定组合 .
我在这个例子中使用PowerShell来调用该方法 .
1
您可以使用CorFlagsCLI工具(例如,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
打开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
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;
}
}
如果下面的批处理文件针对非托管 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.
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
242
另一种方法是使用dumpbinDLL上的Visual Studio工具并查找适当的输出
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 OF THE DLL>
9
更通用的方法 - 使用文件结构来确定位数和图像类型:
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);
}
}
14 回答
看看
System.Reflection.AssemblyName.GetAssemblyName(string assemblyFile)
您可以从返回的AssemblyName实例检查程序集元数据:
使用 PowerShell :
在这里,ProcessorArchitecture标识目标平台 .
Amd64 :基于x64架构的64位处理器 .
Arm :ARM处理器 .
IA64 :仅限64位Intel Itanium处理器 .
MSIL :关于处理器和每字位数的中性 .
X86 :32位Intel处理器,可以是64位平台(WOW64)上的本机或Windows环境中的Windows .
None :处理器和每字位数的未知或未指定组合 .
我在这个例子中使用PowerShell来调用该方法 .
您可以使用CorFlags CLI工具(例如,C:\ Program Files \ Microsoft SDKs \ Windows \ v7.0 \ Bin \ CorFlags.exe)根据其输出确定程序集的状态,并将程序集打开为二进制资产,您应该能够确定在何处需要设置以确定32BIT标志是设置为1(x86)还是0(任何CPU或x64,具体取决于
PE
):博文x64 Development with .NET有一些关于
corflags
的信息 .更好的是,您可以use 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
你会得到这样的输出:
根据评论,上面的标志应如下所示:
任何CPU:PE = PE32和32BIT = 0
x86:PE = PE32且32BIT = 1
64位:PE = PE32且32BIT = 0
你怎么写你自己?自从在Windows 95中实现以来,PE体系结构的核心并没有被严重改变 . 这是一个C#示例:
现在的当前常量是:
但是使用这种方法,它允许新常量的可能性,只需在您认为合适时验证返回 .
尝试使用CorFlagsReader from this project at CodePlex . 它没有引用其他程序集,它可以按原样使用 .
来自JetBrians的DotPeek提供了快速简便的方法来查看msil(anycpu),x86,x64
下面是一个批处理文件,它将针对当前工作目录和所有子目录中的所有
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
. 或者你可以从它的default location复制它 .如果下面的批处理文件针对非托管
dll
或exe
运行,它将错误地将其显示为x86
,因为Corflags.exe
的实际输出将是类似于以下内容的错误消息:我克隆了一个超级方便的工具,它为Windows资源管理器中的程序集添加了一个上下文菜单条目,以显示所有可用的信息:
从这里下载:https://github.com/tebjan/AssemblyInformation/releases
检查.NET程序集的目标平台的另一种方法是使用.NET Reflector检查程序集...
@#〜#€〜!我刚刚意识到新版本不是免费的!因此,更正,如果您有免费版本的.NET反射器,您可以使用它来检查目标平台 .
cfeduke注意到调用GetPEKind的可能性 . 从PowerShell执行此操作可能很有趣 .
例如,这里是可以使用的cmdlet的代码:https://stackoverflow.com/a/16181743/64257
或者,在https://stackoverflow.com/a/4719567/64257处注意到“PowerShell Community Extensions中还有可用于测试可执行映像的Get-PEHeader cmdlet . ”
您可以在此处找到更高级的应用程序:CodePlex - ApiChange
例子:
另一种方法是使用dumpbinDLL上的Visual Studio工具并查找适当的输出
注意:o / p以上是32位dll
dumpbin.exe的另一个有用选项是/ EXPORTS,它将显示dll公开的函数
更通用的方法 - 使用文件结构来确定位数和图像类型:
编译模式枚举
源代码及GitHub解释