Как определить, была ли сборка .NET построена для x86 или x64? - PullRequest
300 голосов
/ 07 ноября 2008

У меня есть произвольный список сборок .NET.

Мне нужно программно проверить, была ли каждая DLL создана для x86 (в отличие от x64 или любого процессора). Это возможно?

Ответы [ 14 ]

1 голос
/ 04 октября 2016

Более продвинутое приложение для этого вы можете найти здесь: CodePlex - ApiChange

Примеры:

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
1 голос
/ 24 апреля 2013

cfeduke отмечает возможность вызова GetPEKind. Это потенциально интересно сделать из PowerShell.

Вот, например, код для используемого командлета: https://stackoverflow.com/a/16181743/64257

В качестве альтернативы на https://stackoverflow.com/a/4719567/64257 отмечается, что «есть также командлет Get-PEHeader в Расширения сообщества PowerShell , который можно использовать для тестирования исполняемых образов».

1 голос
/ 04 августа 2011

Другим способом проверки целевой платформы сборки .NET является проверка сборки с помощью .NET Reflector ...

@ # ~ # € ~! Я только что понял, что новая версия не бесплатна! Итак, исправление: если у вас есть бесплатная версия .NET рефлектора, вы можете использовать ее для проверки целевой платформы.

0 голосов
/ 27 марта 2018

Более общий способ - используйте файловую структуру для определения битности и типа изображения:

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);
    }
}

Перечисление в режиме компиляции

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

Исходный код с объяснением на GitHub

...