Sprawdź, czy niezarządzana biblioteka DLL jest 32-bitowa czy 64-bitowa?

Jak mogę programowo stwierdzić w C# Czy niezarządzanym plikiem DLL jest x86 lub x64?

Author: Peter Mortensen, 2009-06-16

4 answers

Zobacz specyfikacje. Oto podstawowa implementacja:

public static MachineType GetDllMachineType(string dllPath)
{
    // See http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx
    // Offset to PE header is always at 0x3C.
    // The PE header starts with "PE\0\0" =  0x50 0x45 0x00 0x00,
    // followed by a 2-byte machine type field (see the document above for the enum).
    //
    FileStream fs = new FileStream(dllPath, FileMode.Open, FileAccess.Read);
    BinaryReader br = new BinaryReader(fs);
    fs.Seek(0x3c, SeekOrigin.Begin);
    Int32 peOffset = br.ReadInt32();
    fs.Seek(peOffset, SeekOrigin.Begin);
    UInt32 peHead = br.ReadUInt32();

    if (peHead!=0x00004550) // "PE\0\0", little-endian
        throw new Exception("Can't find PE header");

    MachineType machineType = (MachineType) br.ReadUInt16();
    br.Close();
    fs.Close();
    return machineType;
}

MachineType enum jest zdefiniowane jako:

public enum MachineType : ushort
{
    IMAGE_FILE_MACHINE_UNKNOWN = 0x0,
    IMAGE_FILE_MACHINE_AM33 = 0x1d3,
    IMAGE_FILE_MACHINE_AMD64 = 0x8664,
    IMAGE_FILE_MACHINE_ARM = 0x1c0,
    IMAGE_FILE_MACHINE_EBC = 0xebc,
    IMAGE_FILE_MACHINE_I386 = 0x14c,
    IMAGE_FILE_MACHINE_IA64 = 0x200,
    IMAGE_FILE_MACHINE_M32R = 0x9041,
    IMAGE_FILE_MACHINE_MIPS16 = 0x266,
    IMAGE_FILE_MACHINE_MIPSFPU = 0x366,
    IMAGE_FILE_MACHINE_MIPSFPU16 = 0x466,
    IMAGE_FILE_MACHINE_POWERPC = 0x1f0,
    IMAGE_FILE_MACHINE_POWERPCFP = 0x1f1,
    IMAGE_FILE_MACHINE_R4000 = 0x166,
    IMAGE_FILE_MACHINE_SH3 = 0x1a2,
    IMAGE_FILE_MACHINE_SH3DSP = 0x1a3,
    IMAGE_FILE_MACHINE_SH4 = 0x1a6,
    IMAGE_FILE_MACHINE_SH5 = 0x1a8,
    IMAGE_FILE_MACHINE_THUMB = 0x1c2,
    IMAGE_FILE_MACHINE_WCEMIPSV2 = 0x169,
}

Potrzebowałem tylko trzech z nich, ale dodałem je wszystkie dla kompletności. Ostateczne sprawdzenie 64-bitowe:

// Returns true if the dll is 64-bit, false if 32-bit, and null if unknown
public static bool? UnmanagedDllIs64Bit(string dllPath)
{
    switch (GetDllMachineType(dllPath))
    {
        case MachineType.IMAGE_FILE_MACHINE_AMD64:
        case MachineType.IMAGE_FILE_MACHINE_IA64:
            return true;
        case MachineType.IMAGE_FILE_MACHINE_I386:
            return false;
        default:
            return null;
    }
}
 45
Author: yoyoyoyosef,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-28 13:40:03

Używanie wiersza poleceń Visual Studio, dumpbin / headers dllname.dll działa zbyt. Na mojej maszynie początek wyjścia podano:

FILE HEADER VALUES
8664 machine (x64)
5 number of sections
47591774 time date stamp Fri Dec 07 03:50:44 2007
 20
Author: David Silva Smith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-07 17:31:48

Jeszcze łatwiej: sprawdź System.Odbicie.Klasa modułu. Zawiera on metodę GetPEKind, która zwraca 2 liczby opisujące typ kodu i cel procesora. Koniec z zaklęciami!

(reszta tego bardzo pouczającego postu została skopiowana bezwstydnie z http://www.developersdex.com/vb/message.asp?p=2924&r=6413567 )

Przykładowy kod:

Assembly assembly = Assembly.ReflectionOnlyLoadFrom(@"<assembly Path>");
PortableExecutableKinds kinds;
ImageFileMachine imgFileMachine;
assembly.ManifestModule.GetPEKind(out kinds, out imgFileMachine);

PortableExecutableKinds mogą być użyte do sprawdzenia, jakiego rodzaju zespół. Informatyka ma 5 wartości:

ILOnly: The program wykonywalny zawiera tylko Microsoft intermediate language (MSIL), a zatem jest neutralny w odniesieniu do 32-bitowych lub 64-bitowych perony.

NotAPortableExecutableImage: plik nie jest w przenośnym pliku wykonywalnym (PE) format pliku.

PE32Plus: plik wykonywalny wymaga 64-bitowej platformy.

Required32Bit: plik wykonywalny może być uruchomiony na platformie 32-bitowej lub w 32-bitowe środowisko Windows on Windows (WOW) na platformie 64-bitowej.

Unmanaged32Bit: plik wykonywalny zawiera czysty niezarządzany kod.

Poniżej znajdują się linki:

Moduł.Metoda GetPEKind: http://msdn.microsoft.com/en-us/library/system.reflection.module.getpekind.aspx

PortableExecutableKinds: http://msdn.microsoft.com/en-us/library/system.reflection.portableexecutablekinds(VS.80).aspx

Imagefilemachine Enumeration: http://msdn.microsoft.com/en-us/library/system.reflection.imagefilemachine.aspx

 4
Author: muusbolla,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-17 22:26:33

Zamiast Assembly.LoadFile, użyj Assembly.ReflectionOnlyLoadFrom. Pozwoli to obejść wyjątki "zły Format obrazu".

 1
Author: user1383112,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-20 16:07:24