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

后端 未结 15 1153
面向向阳花
面向向阳花 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: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

提交回复
热议问题