我有一个任意的。net程序集列表。
我需要以编程方式检查每个DLL是否为x86构建(而不是x64或任何CPU)。这可能吗?
我有一个任意的。net程序集列表。
我需要以编程方式检查每个DLL是否为x86构建(而不是x64或任何CPU)。这可能吗?
当前回答
您可以使用CorFlags命令行工具(例如,C:\Program Files\Microsoft sdk \Windows\v7.0\Bin\CorFlags.exe)来确定程序集的状态,根据其输出并将程序集作为二进制资产打开,您应该能够确定您需要在哪里查找,以确定32位标志是否设置为1 (x86)或0(任何CPU或x64,取决于PE):
Option | PE | 32BIT
----------|-------|---------
x86 | PE32 | 1
Any CPU | PE32 | 0
x64 | PE32+ | 0
博客文章x64 Development with . net有一些关于corflags的信息。
更好的是,您可以使用Module。GetPEKind来确定程序集是否为portableexecutabletypes值PE32Plus(64位)、Required32Bit(32位和WoW)或ILOnly(任何CPU)以及其他属性。
其他回答
检查.NET程序集的目标平台的另一种方法是使用.NET Reflector检查程序集…
@ # ~ #€~ !我刚刚意识到新版本不是免费的!因此,更正一下,如果你有一个。net reflector的免费版本,你可以用它来检查目标平台。
下面是一个批处理文件,它将针对当前工作目录和所有子目录中的所有DLL文件和EXE文件运行corflags.exe,解析结果并显示每个目标体系结构。
Depending on the version of corflags.exe that is used, the line items in the output will either include 32BIT, or 32BITREQ (and 32BITPREF). Whichever of these two is included in the output is the critical line item that must be checked to differentiate between Any CPU and x86. If you are using an older version of corflags.exe (pre Windows SDK v8.0A), then only the 32BIT line item will be present in the output, as others have indicated in past answers. Otherwise 32BITREQ and 32BITPREF replace it.
这假设corflags.exe在%PATH%. exe文件中。确保这一点的最简单方法是使用开发人员命令提示符。或者,您也可以从默认位置复制它。
如果下面的批处理文件是针对一个非托管DLL或EXE文件运行的,它将错误地显示为x86,因为Corflags.exe的实际输出将是一个类似于:
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.
我喜欢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或任何其他版本:
还有一种方法是在DLL上使用Visual Studio工具中的dumpbin,并寻找适当的输出:
dumpbin.exe /HEADERS <your DLL file 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
注意:上面的输出是一个32位DLL文件
dumpbin.exe的一个更有用的选项是/EXPORTS。它将显示DLL文件公开的函数
dumpbin.exe /EXPORTS <PATH OF THE DLL FILE>
你自己写就行了。PE架构的核心自从在Windows 95中实现以来就没有发生过重大变化。
下面是一个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))
{
// Check the MZ signature
if (bReader.ReadUInt16() == 23117)
{
// Seek to e_lfanew.
fStream.Seek(0x3A, System.IO.SeekOrigin.Current);
// Seek to the start of the NT header.
fStream.Seek(bReader.ReadUInt32(), System.IO.SeekOrigin.Begin);
if (bReader.ReadUInt32() == 17744) // Check the PE\0\0 signature.
{
// Seek past the file header,
fStream.Seek(20, System.IO.SeekOrigin.Current);
// Read the magic number of the optional header.
architecture = bReader.ReadUInt16();
}
}
}
}
}
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.
但是用这种方法,它允许新常数的可能性。只要验证你认为合适的返回。