如何确定.NET程序集是为x86还是x64构建的?

Jud*_*ngo 312 .net 64-bit x86 assemblies x86-64

我有一个任意的.NET程序集列表.

我需要以编程方式检查每个DLL是否是为x86构建的(而不是x64或任何CPU).这可能吗?

x0n*_*x0n 268

看着 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来调用该方法.

  • 原谅这个愚蠢的问题 - 但是这会告诉你它是什么? (60认同)
  • ProcessorArchitecture字段是枚举; 在上面的示例中,它设置为MSIL,这意味着"相对于处理器是中性的,每个字位数".其他值包括X86,IA64,Amd64.有关详细信息,请参阅http://msdn.microsoft.com/en-us/library/system.reflection.processorarchitecture.aspx. (53认同)
  • 尝试使用`[reflection.assemblyname] :: GetAssemblyName("$ {pwd} \name.dll")`,因为有时进程的当前目录与当前提供程序不同(我假设DLL适合您) (4认同)
  • 我在尝试使用 PowerShell 时遇到以下错误:`用“1”参数调用“GetAssemblyName”的异常:“无法加载文件或程序集 '[DLLName].dll' 或其依赖项之一。系统找不到指定的文件。”`(是的,我拼写正确)。 (2认同)
  • 需要注意的另一个警告是,如果从互联网下载DLL,则忘记"解锁"DLL.使用unblock-file,或右键单击/ properties /从资源管理器中取消阻止.如果您在当前会话中已经失败一次,则需要重新启动shell才能识别未阻止的状态(责怪Internet Explorer也是如此 - 是的,真的.) (2认同)

cfe*_*uke 219

您可以使用CorFlags CLI工具(例如,C:\ Program Files\Microsoft SDKs\Windows\v7.0\Bin\CorFlags.exe)根据其输出确定程序集的状态,并将程序集作为二进制资产,您应该能够确定在何处需要设置以确定32BIT标志是设置为1(x86)还是0(任何CPUx64,具体取决于PE):

Option    | PE    | 32BIT
----------|-------|---------
x86       | PE32  | 1
Any CPU   | PE32  | 0
x64       | PE32+ | 0
Run Code Online (Sandbox Code Playgroud)

博客文章x64开发与.NET有一些信息corflags.

更好的是,您可以使用它Module.GetPEKind来确定程序集是PortableExecutableKindsPE32Plus(64位),Required32Bit(32位和WOW)还是ILOnly(任何CPU)以及其他属性.

  • 检查32位程序集时,GetPEKind在64位进程中失败 (9认同)
  • 正如[本回答](http://stackoverflow.com/a/23614024/134761)中所指出的,在.NET 4.5中有32BITREQ和32BITPREF而不是32BIT标志.PE32/0/0和PE32/0/1分别是AnyCPU和AnyCPU 32位优选. (5认同)
  • 你必须从32位进程调用GetPEKind (2认同)
  • 我安装了VS 2008,VS 2010,VS 2012和VS 2013.我在C:\ Program Files(x86)\ Microsoft SDKs\Windows \的子文件夹中有8个文件CorFlags.exe.哪个我应该用? (2认同)

Jos*_*shL 138

只是为了澄清,CorFlags.exe是.NET Framework SDK的一部分.我在我的机器上有开发工具,我最简单的方法是确定DLL是否只是32位是:

  1. 打开Visual Studio命令提示符(在Windows中:菜单"开始"/"程序"/"Microsoft Visual Studio/Visual Studio工具/ Visual Studio 2008命令提示符")

  2. CD到包含有问题的DLL的目录

  3. 像这样运行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
Run Code Online (Sandbox Code Playgroud)

根据评论,上面的标志应如下所示:

  • 任何CPU:PE = PE32和32BIT = 0
  • x86:PE = PE32和32BIT = 1
  • 64位:PE = PE32 +和32BIT = 0

  • 这似乎同时发生了变化; corflags现在显示`32BITREQ`和`32BITPREF`而不是单个`32BIT`值. (12认同)
  • “Visual Studio 命令提示符”现在称为“[Visual Studio 2019 开发人员命令提示符](https://learn.microsoft.com/en-us/dotnet/framework/tools/developer-command-prompt-for-vs) ”。 (3认同)

小智 19

你怎么写你自己?自从在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;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在的当前常量是:

0x10B - PE32  format.
0x20B - PE32+ format.
Run Code Online (Sandbox Code Playgroud)

但是使用这种方法,它允许新常量的可能性,只需在您认为合适时验证返回.

  • 非常有趣,但是当我使用Any CPU编译应用程序时,结果是0x10B.这是错误的,因为我的应用程序是在x64系统中运行的.还有其他标志要检查吗? (3认同)

Lud*_*dwo 9

尝试在CodePlex中使用此项目中的 CorFlagsReader .它没有引用其他程序集,它可以按原样使用.


小智 7

来自JetBrians的DotPeek提供了快速简便的方法来查看msil(anycpu),x86,x64 dotPeek


Mor*_*lor 6

[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);
    }
}
Run Code Online (Sandbox Code Playgroud)


Eri*_*ase 5

下面是将运行一个批处理文件,corflags.exe对所有dllsexes当前工作目录及其所有子目录,解析结果,并显示每个目标架构。

取决于版本corflags.exe所使用,在输出线的项目将包括32BIT 32BITREQ(及32BITPREF)。输出中包括这两者中的哪一个是关键行项目,必须对其进行检查以区分Any CPUx86。如果您使用的是旧版本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.
Run Code Online (Sandbox Code Playgroud)