47 votes

Vérifier si la DLL non gérée est 32-bit ou 64-bit ?

Comment puis-je dire de façon programmatique en C# si une non géré Le fichier DLL est x86 ou x64 ?

0 votes

0 votes

50voto

yoyoyoyosef Points 2311

Se référer à les spécifications . Voici une mise en œuvre de base :

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).
    //
    using (var fs = new FileStream (dllPath, FileMode.Open, FileAccess.Read))
    using (var 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");

        return (MachineType)br.ReadUInt16();
    }
}

Le site MachineType est défini comme suit :

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,
    IMAGE_FILE_MACHINE_ARM64 = 0xaa64 
}

Je n'ai eu besoin que de trois d'entre eux, mais je les ai tous inclus pour être complet. Vérification finale pour les 64 bits :

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

0 votes

J'ai ajouté FileAccess.Read à l'instanciation de votre FileStream - sinon, il nous fait faux bond lorsque nous essayons de déterminer le bitness des DLL dans l'un ou l'autre des cas suivants C:\Windows ou C:\Program Archivos

0 votes

GetPEKind ( msdn.microsoft.com/fr/us/library/ ) échoue dans un processus 64 bits lors de la vérification d'assemblages 32 bits. Votre code fonctionne-t-il à ce sujet ?

21voto

David Silva Smith Points 3350

En utilisant une invite de commande Visual Studio, dumpbin /headers dllname.dll fonctionne également. Sur ma machine, le début de la sortie indique :

FILE HEADER VALUES
8664 machine (x64)
5 number of sections
47591774 time date stamp Fri Dec 07 03:50:44 2007

7voto

Lazarus Points 17526

5voto

muusbolla Points 196

Encore plus facile : consultez la classe System.Reflection.Module. Elle comprend la méthode GetPEKind, qui renvoie 2 enums décrivant le type de code et la cible CPU. Fini l'hexagone !

(le reste de ce billet très instructif a été copié sans vergogne de http://www.developersdex.com/vb/message.asp?p=2924&r=6413567 )

Exemple de code :

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

PortableExecutableKinds peut être utilisé pour vérifier le type d'assemblage. Il s'agit de a 5 valeurs :

Seulement le BIT : L'exécutable ne contient que le langage intermédiaire de Microsoft (MSIL), et est donc neutre par rapport aux plateformes 32 ou 64 bits. ou 64 bits.

NotAPortableExecutableImage : Le fichier n'est pas au format de fichier exécutable portable (PE). format de fichier.

PE32Plus : L'exécutable nécessite une plate-forme 64 bits.

Required32Bit : L'exécutable peut être exécuté sur une plateforme 32 bits, ou dans le format environnement 32 bits Windows on Windows (WOW) sur une plate-forme 64 bits.

Unmanaged32Bit : L'exécutable contient du code pur non géré.

Voici les liens :

Module.GetPEKind Méthode : http://msdn.microsoft.com/en-us/library/system.reflection.module.getpekind.aspx

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

Enumération ImageFileMachine : http://msdn.microsoft.com/en-us/library/system.reflection.imagefilemachine.aspx

9 votes

Cela ne fonctionne que si vous pouvez effectivement charger l'assemblage dans votre processus. Si le type de machine et le bitness ne correspondent pas, vous obtiendrez une exception "Bad Image Format" à Assembly.LoadFile() et vous n'arriverez jamais à GetPEKind().

1voto

user1383112 Points 1

Au lieu de Assembly.LoadFile utiliser Assembly.ReflectionOnlyLoadFrom . Cela vous permettra de contourner les exceptions liées au "mauvais format d'image".

0 votes

Je reçois toujours un System.BadImageFormatException lors de l'utilisation de Assembly.ReflectionOnlyLoadFrom malheureusement.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X