35

What's the easiest way to discover (without access to the source project) whether a .NET assembly DLL was compiled as 'x86', 'x64' or 'Any CPU'?

Update: A command-line utility was sufficient to meet my immediate needs, but just for the sake of completeness, if someone wants to tell me how to do it programmatically then that would be of interest too, I'm sure.

Tim Long
  • 13,508
  • 19
  • 79
  • 147
  • I would recommend searching through the ISA's for x86 and x64 and generate the set of different instructions between the two. Then I would search the dll binaries for those differences and (hopefully) that gives you the result you want. Even so this sounds hard, error prone, and I wouldn't recommend it. (I don't know if the dll contains this information itself) – Robert Massaioli Oct 19 '09 at 22:51
  • Are you looking for a tool or how to do this yourself programmatically? – pbz Oct 19 '09 at 22:56
  • Ideally, right-click / properties / details , but alas :( – Colonel Panic Nov 13 '12 at 17:21
  • possible duplicate of [How to determine if a .NET assembly was built for x86 or x64?](http://stackoverflow.com/questions/270531/how-to-determine-if-a-net-assembly-was-built-for-x86-or-x64) – Blorgbeard Nov 15 '12 at 20:03
  • [As a .bat file](http://stackoverflow.com/a/36316170/4342563) – Eric Lease Mar 30 '16 at 17:59

4 Answers4

52

If you just want to find this out on a given dll, then you can use the CorFlags tool that is part of the Windows SDK:

CorFlags.exe assembly.dll

If you want to do it using code, take a look at the GetPEKind method of the Module class:

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

You then need to examine the peKind to check its value. See the MSDN docs for PortableExecutableKinds for more info.

Colonel Panic
  • 132,665
  • 89
  • 401
  • 465
adrianbanks
  • 81,306
  • 22
  • 176
  • 206
  • 1
    Thanks. I ran `CorFlags.exe` but I don't understand how to read the output. What would I see were the assembly x86/x64/AnyCPU? – Colonel Panic Nov 13 '12 at 17:24
  • 2
    @ColonelPanic: Look for the `32BIT` flag. If it is `1`, then the assembly is compiled for 32-bit only. – adrianbanks Nov 14 '12 at 11:51
  • I install VS 2008, VS 2010, VS 2012 and VS 2013. I have 8 files CorFlags.exe in subfolders in C:\Program Files (x86)\Microsoft SDKs\Windows\. Which I should be use ? – Kiquenet Mar 25 '14 at 15:05
  • 1
    @Kiquenet: I would use the latest one (i.e. the one from the folder with the highest version number). – adrianbanks Mar 25 '14 at 21:37
14

Thanks Adrian! I've rewritten the snippet in PowerShell so I could use it on the server.

#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
}
Peter Seale
  • 4,835
  • 4
  • 37
  • 45
3

Thanks Adrian and Peter! Here's a modified version of Peter's Get-Bitness that 1) takes a list of files to examine from the pipeline, and 2) doesn't die it if looks at a non-.NET DLL (e.g. if it looks at certain C++ DLLs):

# 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
        }
    }
}

I'm new to PowerShell, so this may not be an example of best practices.

Alternatively, according to https://stackoverflow.com/a/4719567/64257 there may also be a handy Get-PEHeader cmdlet in the PowerShell Community Extensions.

Community
  • 1
  • 1
Chris
  • 9,986
  • 8
  • 48
  • 56
3

C# snippet, based on the Powershell answers:

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();
fiat
  • 15,501
  • 9
  • 81
  • 103