【问题标题】:How to Tell if a .NET Assembly Was Compiled as x86, x64 or Any CPU如何判断 .NET 程序集是否编译为 x86、x64 或任何 CPU
【发布时间】:2010-12-08 04:09:09
【问题描述】:

发现(无需访问源项目).NET 程序集 DLL 是编译为“x86”、“x64”还是“Any CPU”的最简单方法是什么?

更新:命令行实用程序足以满足我的即时需求,但只是为了完整起见,如果有人想告诉我如何以编程方式完成它,那我肯定也会感兴趣。

【问题讨论】:

  • 我建议在 ISA 中搜索 x86 和 x64,并在两者之间生成一组不同的指令。然后我会在 dll 二进制文件中搜索这些差异,并且(希望)能够为您提供所需的结果。即便如此,这听起来很难,容易出错,我不推荐它。 (不知道dll本身是否包含这些信息)
  • 您是否正在寻找一种工具或如何以编程方式自己完成这项工作?
  • 理想情况下,右键单击/properties/details,但是唉:(

标签: .net visual-studio x86-64


【解决方案1】:

如果您只想在给定的 dll 上找到它,那么您可以使用 Windows SDK 中的CorFlags 工具:

CorFlags.exe assembly.dll

如果你想用代码来做,看看Module类的GetPEKind方法:

Assembly assembly = Assembly.LoadFrom("path to dll");
PortableExecutableKinds peKind;
ImageFileMachine imageFileMachine;
assembly.ManifestModule.GetPEKind(out peKind, out imageFileMachine)

然后您需要检查peKind 以检查其值。有关更多信息,请参阅MSDN docs for PortableExecutableKinds

【讨论】:

  • 谢谢。我跑了CorFlags.exe,但我不明白如何读取输出。我会看到什么是 x86/x64/AnyCPU 组件?
  • @ColonelPanic:寻找32BIT 标志。如果是1,则程序集仅编译为 32 位。
  • 我安装了 VS 2008、VS 2010、VS 2012 和 VS 2013。我在 C:\Program Files (x86)\Microsoft SDKs\Windows\ 的子文件夹中有 8 个文件 CorFlags.exe。我应该使用哪个?
  • @Kiquenet:我会使用最新的(即版本号最高的文件夹中的那个)。
【解决方案2】:

谢谢阿德里安!我已经在 PowerShell 中重写了 sn-p,以便可以在服务器上使用它。

#USAGE #1
# Get-Bitness (dir *.dll | select -first 1)
#USAGE #2
# Get-Bitness "C:\vs\projects\bestprojectever\bin\debug\mysweetproj.dll"
function Get-Bitness([System.IO.FileInfo]$assemblyFile)
{
    $peKinds = new-object Reflection.PortableExecutableKinds
    $imageFileMachine = new-object Reflection.ImageFileMachine
    $a = [Reflection.Assembly]::LoadFile($assemblyFile.Fullname)
    $a.ManifestModule.GetPEKind([ref]$peKinds, [ref]$imageFileMachine)

    return $peKinds
}

【讨论】:

  • 太棒了。如果可以的话,我会给它+2
【解决方案3】:

感谢阿德里安和彼得!这是 Peter 的 Get-Bitness 的修改版本,它 1) 从管道中获取要检查的文件列表,以及 2) 如果查看非 .NET DLL(例如,如果它查看某些 C++ DLL),它不会死掉:

# example usage: dir *.exe,*.dll | Get-PEKind
function Get-PEKind {
    Param(
      [Parameter(Mandatory=$True,ValueFromPipeline=$True)]
      [System.IO.FileInfo]$assemblies
    )

    Process {
        foreach ($assembly in $assemblies) {
            $peKinds = new-object Reflection.PortableExecutableKinds
            $imageFileMachine = new-object Reflection.ImageFileMachine
            try
            {
                $a = [Reflection.Assembly]::LoadFile($assembly.Fullname)
                $a.ManifestModule.GetPEKind([ref]$peKinds, [ref]$imageFileMachine)
            }
            catch [System.BadImageFormatException]
            {
                $peKinds = [System.Reflection.PortableExecutableKinds]"NotAPortableExecutableImage"
            }

            $o = New-Object System.Object
            $o | Add-Member -type NoteProperty -name File -value $assembly
            $o | Add-Member -type NoteProperty -name PEKind -value $peKinds
            Write-Output $o
        }
    }
}

我是 PowerShell 新手,因此这可能不是最佳实践示例。

或者,根据https://stackoverflow.com/a/4719567/64257PowerShell Community Extensions 中可能还有一个方便的 Get-PEHeader cmdlet。

【讨论】:

    【解决方案4】:

    C# sn-p,基于 Powershell 答案:

    var modules = assembly.GetModules();
    var kinds = new List<PortableExecutableKinds>();
    var images = new List<ImageFileMachine>();
    foreach (var module in modules)
    {
        PortableExecutableKinds peKinds;
        ImageFileMachine imageFileMachine;
        module.GetPEKind(out peKinds, out imageFileMachine);
    
        kinds.Add(peKinds);
        images.Add(imageFileMachine);
    }
    
    var distinctKinds = kinds.Distinct().ToList();
    var distinctImages = images.Distinct().ToList();
    

    【讨论】:

      猜你喜欢
      • 2010-11-28
      • 2023-03-03
      • 2013-10-06
      • 2010-12-03
      • 2016-04-17
      • 1970-01-01
      • 2021-05-21
      相关资源
      最近更新 更多