How to Tell if a .NET Assembly Was Compiled as x86, x64 or Any CPU
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.
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();
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
}
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.