How can I determine if a .NET assembly was built for x86 or x64?

后端 未结 15 880
面向向阳花
面向向阳花 2020-11-22 09:08

I\'ve got an arbitrary list of .NET assemblies.

I need to programmatically check if each DLL was built for x86 (as opposed to x64 or Any CPU). Is this possible?

相关标签:
15条回答
  • 2020-11-22 09:36

    An alternative to already mentioned tools is Telerik JustDecompile (free tool) which will display the information next to the assembly name:

    0 讨论(0)
  • 2020-11-22 09:41

    cfeduke notes the possibility of calling GetPEKind. It's potentially interesting to do this from PowerShell.

    Here, for example, is code for a cmdlet that could be used: https://stackoverflow.com/a/16181743/64257

    Alternatively, at https://stackoverflow.com/a/4719567/64257 it is noted that "there's also the Get-PEHeader cmdlet in the PowerShell Community Extensions that can be used to test for executable images."

    0 讨论(0)
  • 2020-11-22 09:43

    Another way to check the target platform of a .NET assembly is inspecting the assembly with .NET Reflector...

    @#~#€~! I've just realized that the new version is not free! So, correction, if you have a free version of .NET reflector, you can use it to check the target platform.

    0 讨论(0)
  • 2020-11-22 09:45

    A more advanced application for that you can find here: CodePlex - ApiChange

    Examples:

    C:\Downloads\ApiChange>ApiChange.exe -CorFlags c:\Windows\winhlp32.exe
    File Name; Type; Size; Processor; IL Only; Signed
    winhlp32.exe; Unmanaged; 296960; X86
    
    C:\Downloads\ApiChange>ApiChange.exe -CorFlags c:\Windows\HelpPane.exe
    File Name; Type; Size; Processor; IL Only; Signed
    HelpPane.exe; Unmanaged; 733696; Amd64
    
    0 讨论(0)
  • 2020-11-22 09:46

    One more way would be to use dumpbin from the Visual Studio tools on DLL and look for the appropriate output

    dumpbin.exe /HEADERS <your dll path>
        FILE HEADER VALUE
                     14C machine (x86)
                       4 number of sections
                5885AC36 time date stamp Mon Jan 23 12:39:42 2017
                       0 file pointer to symbol table
                       0 number of symbols
                      E0 size of optional header
                    2102 characteristics
                           Executable
                           32 bit word machine
                           DLL
    

    Note: Above o/p is for 32bit dll

    One more useful option with dumpbin.exe is /EXPORTS, It will show you the function exposed by the dll

    dumpbin.exe /EXPORTS <PATH OF THE DLL>
    
    0 讨论(0)
  • 2020-11-22 09:46

    More generic way - use file structure to determine bitness and image type:

    public static CompilationMode GetCompilationMode(this FileInfo info)
    {
        if (!info.Exists) throw new ArgumentException($"{info.FullName} does not exist");
    
        var intPtr = IntPtr.Zero;
        try
        {
            uint unmanagedBufferSize = 4096;
            intPtr = Marshal.AllocHGlobal((int)unmanagedBufferSize);
    
            using (var stream = File.Open(info.FullName, FileMode.Open, FileAccess.Read))
            {
                var bytes = new byte[unmanagedBufferSize];
                stream.Read(bytes, 0, bytes.Length);
                Marshal.Copy(bytes, 0, intPtr, bytes.Length);
            }
    
            //Check DOS header magic number
            if (Marshal.ReadInt16(intPtr) != 0x5a4d) return CompilationMode.Invalid;
    
            // This will get the address for the WinNT header  
            var ntHeaderAddressOffset = Marshal.ReadInt32(intPtr + 60);
    
            // Check WinNT header signature
            var signature = Marshal.ReadInt32(intPtr + ntHeaderAddressOffset);
            if (signature != 0x4550) return CompilationMode.Invalid;
    
            //Determine file bitness by reading magic from IMAGE_OPTIONAL_HEADER
            var magic = Marshal.ReadInt16(intPtr + ntHeaderAddressOffset + 24);
    
            var result = CompilationMode.Invalid;
            uint clrHeaderSize;
            if (magic == 0x10b)
            {
                clrHeaderSize = (uint)Marshal.ReadInt32(intPtr + ntHeaderAddressOffset + 24 + 208 + 4);
                result |= CompilationMode.Bit32;
            }
            else if (magic == 0x20b)
            {
                clrHeaderSize = (uint)Marshal.ReadInt32(intPtr + ntHeaderAddressOffset + 24 + 224 + 4);
                result |= CompilationMode.Bit64;
            }
            else return CompilationMode.Invalid;
    
            result |= clrHeaderSize != 0
                ? CompilationMode.CLR
                : CompilationMode.Native;
    
            return result;
        }
        finally
        {
            if (intPtr != IntPtr.Zero) Marshal.FreeHGlobal(intPtr);
        }
    }
    

    Compilation mode enumeration

    [Flags]
    public enum CompilationMode
    {
        Invalid = 0,
        Native = 0x1,
        CLR = Native << 1,
        Bit32 = CLR << 1,
        Bit64 = Bit32 << 1
    }
    

    Source code with explanation at GitHub

    0 讨论(0)
提交回复
热议问题