当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《如何确定.NET程序集是为x86还是x64构建的?》经验,为你挑选了8个好方法。

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

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



1> x0n..:

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


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

2> cfeduke..:

您可以使用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

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

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


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

3> JoshL..:

只是为了澄清,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


这似乎同时发生了变化; corflags现在显示`32BITREQ`和`32BITPREF`而不是单个`32BIT`值.

4> 小智..:

你怎么写你自己?自从在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.

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


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

5> Ludwo..:

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



6> 小智..:

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



7> Morgan Mello..:
[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);
    }
}



8> Eric Lease..:

下面是将运行一个批处理文件,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.

推荐阅读
勤奋的瞌睡猪_715
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有