Frage

Wie kann ich programmatisch in C # sagen, wenn ein nicht verwaltete DLL-Datei x86 oder x64 ist?

War es hilfreich?

Lösung

Siehe href="http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx" zum die Spezifikationen . Hier ist eine grundlegende Implementierung:

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

Die MachineType Enum ist definiert als:

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,
}

Ich brauchte nur drei von ihnen, aber ich eingeschlossen, sie alle auf Vollständigkeit. Finale 64-Bit-Check:

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

Andere Tipps

ein Visual Studio-Eingabeaufforderung, dumpbin / headers Mit dllname.dll auch funktioniert. Auf meinem Rechner erklärte der Anfang der Ausgabe:

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

Noch einfacher: Überprüfen Sie die System.Reflection.Module Klasse aus. Es umfasst die GetPEKind Methode, die 2 enums zurückgibt, der den Typ von Code und die CPU Ziel beschreiben. Nicht mehr hex!

(der Rest dieser sehr informativen Beitrag wurde schamlos von http kopiert : //www.developersdex.com/vb/message.asp p = 2924 & r = 6.413.567 )

Beispielcode:

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

PortableExecutableKinds kann verwendet werden, um zu überprüfen, welche Art der Anordnung. Es hat 5 Werte:

ILONLY: Die ausführbare Datei enthält nur Microsoft Intermediate Language (MSIL), und ist daher neutral in Bezug auf 32-bit oder 64-bit Plattformen.

NotAPortableExecutableImage: Die Datei ist nicht in Portable Executable (PE) Dateiformat.

PE32Plus: Die ausführbare Datei erfordert eine 64-Bit-Plattform

.

Required32Bit: Die ausführbare Datei kann auf einer 32-Bit-Plattform ausgeführt werden, oder in der 32-Bit-Windows auf Windows (WOW) -Umgebung auf einer 64-Bit-Plattform.

Unmanaged32Bit: Die ausführbare Datei enthält reinen unmanaged Code

.

Im Folgenden sind die Verbindungen:

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

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

ImageFileMachine Enumeration: http://msdn.microsoft.com/en-us/ Bibliothek / system.reflection.imagefilemachine.aspx

Statt Assembly.LoadFile, Verwendung Assembly.ReflectionOnlyLoadFrom. Auf diese Weise können Sie rund um die „Bad Format des Bildes“ Ausnahmen arbeiten.

Ich weiß, dass es eine Weile gewesen, da diese aktualisiert. Ich konnte mit den „Bad Format des Bildes“ Ausnahmen wegzukommen, indem Sie die Datei in seinem eigenen AppDomain geladen werden.

        private static (string pkName, string imName) FindPEKind(string filename)
    {
        // some files, especially if loaded into memory
        // can cause errors. Thus, load into their own appdomain
        AppDomain tempDomain = AppDomain.CreateDomain(Guid.NewGuid().ToString());
        PEWorkerClass remoteWorker =
            (PEWorkerClass)tempDomain.CreateInstanceAndUnwrap(
                typeof(PEWorkerClass).Assembly.FullName,
                typeof(PEWorkerClass).FullName);

        (string pkName, string imName) = remoteWorker.TryReflectionOnlyLoadFrom_GetManagedType(filename);

        AppDomain.Unload(tempDomain);
        return (pkName, imName);
    }

An dieser Stelle ich Folgendes tun:

        public (string pkName, string imName) TryReflectionOnlyLoadFrom_GetManagedType(string fileName)
    {
        string pkName;
        string imName;
        try
        {
            Assembly assembly = Assembly.ReflectionOnlyLoadFrom(assemblyFile: fileName);
            assembly.ManifestModule.GetPEKind(
                peKind: out PortableExecutableKinds peKind,
                machine: out ImageFileMachine imageFileMachine);

            // Any CPU builds are reported as 32bit.
            // 32bit builds will have more value for PortableExecutableKinds
            if (peKind == PortableExecutableKinds.ILOnly && imageFileMachine == ImageFileMachine.I386)
            {
                pkName = "AnyCPU";
                imName = "";
            }
            else
            {
                PortableExecutableKindsNames.TryGetValue(
                    key: peKind,
                    value: out pkName);
                if (string.IsNullOrEmpty(value: pkName))
                {
                    pkName = "*** ERROR ***";
                }

                ImageFileMachineNames.TryGetValue(
                    key: imageFileMachine,
                    value: out imName);
                if (string.IsNullOrEmpty(value: pkName))
                {
                    imName = "*** ERROR ***";
                }
            }

            return (pkName, imName);
        }
        catch (Exception ex)
        {
            return (ExceptionHelper(ex), "");
        }
    }

Ausführen dieses gegen meine Widows \ Assembly Verzeichnis gibt mir keine Fehler mit mehr als 3600 Dateien verarbeitet. Folgendes beachten:. Ich verwende ein Wörterbuch der Werte laden zurückgegeben werden

Ich hoffe, es hilft. YMMV

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top