Frage

Was ist der beste Weg, um zu überprüfen, ob eine DLL -Datei eine Win32 -DLL ist oder ob es sich um eine CLR -Montage handelt. Im Moment verwende ich diesen Code

    try
    {
        this.currentWorkingDirectory = Path.GetDirectoryName(assemblyPath);

        //Try to load the assembly.
        assembly = Assembly.LoadFile(assemblyPath);

        return assembly != null;
    }
    catch (FileLoadException ex)
    {
        exception = ex;
    }
    catch (BadImageFormatException ex)
    {
        exception = ex;
    }
    catch (ArgumentException ex)
    {
        exception = ex;
    }
    catch (Exception ex)
    {
        exception = ex;
    }

    if (exception is BadImageFormatException)
    {
        return false;
    }

Aber ich prüfe gerne vor dem Laden, weil ich diese Ausnahmen nicht möchte (Zeit).

Gibt es einen besseren Weg?

War es hilfreich?

Lösung

Überprüfen Sie den PE -Header:

Der DOS -Header beginnt bei 0x0, das DWORD bei 0x3c enthält einen Zeiger auf die PE -Signatur (normalerweise 0x80), die 4 Bytes ist, die nächsten 20 Bytes sind der COUD -Header und dann gibt es den PE -Kopfball (bei 0x9. Der PE -Header ist 224 Bytes und enthält das Datenverzeichnis (bei 96 Bytes in den PE -Header = 0xf. Der 15. Eintrag (bei 0x16 ist der CLR -Header -Deskriptor (manchmal als COM -Deskriptor bezeichnet, aber dies hat nichts mit Com zu tun). Wenn dies ist Leer (dh 0 in den 8 Bytes von 0x168 bis 0x16f) ist die Datei keine .NET -Baugruppe. Wenn Sie überprüfen möchten, ob es sich um eine Komplette handelt, sollten Sie nachsehen, ob es das GetClassObject exporte.

Ref.

AKTUALISIEREN: Es gibt eine bessere Art, dies zu erreichen:

Verwenden Module.GetPEKind Methode und überprüfen Sie die PortableExecutableKinds Aufzählung:

NotaportableExecableable Die Datei befindet sich nicht im Dateiformat für portable ausführbare Datei (PE).

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

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

Pe32plus Die ausführbare Datei erfordert eine 64-Bit-Plattform.

Unmanagiert32bit Die ausführbare Datei enthält einen reinen nicht verwalteten Code.

Andere Tipps

Wenn eine Baugruppe geladen wird, z. Assembly.LoadFile(dotNetDllorExe) Und wirft keine Ausnahme, es ist eine gültige .NET -Montage. Wenn nicht, dann wird es eine "badimageformatexception" werfen.

Die Idee, das Wetter zu überprüfen, ist eine Datei Montage oder nicht, indem sie geladen und prüft, ob eine Ausnahme ausgelöst wird oder nicht. Scheint nicht zu sauber zu sein. Immerhin sollen Ausnahmen außergewöhnlich verwendet werden.


.NET -Assemblys sind reguläre Win32 -PE -Dateien, das Betriebssystem unterscheidet nicht zwischen .NET -Assemblys und win32 ausführbaren Binärdateien, sondern sind dieselben normalen PE -Dateien. Wie funktioniert das System, wenn eine DLL oder eine Exe eine verwaltete Montage ist, um die CLR zu laden?

Es bestätigt den Dateikopf, um zu überprüfen, ob es sich um eine verwaltete Montage handelt oder nicht. In den ECMA -Spezifikationen partition II - Metadaten, die zusammen mit .NET SDK verschickt werden, sehen Sie, dass es im PE -Format einen separaten CLI -Header gibt. Es ist der 15. Datenverzeichnis im pe -optionalen Header. Wenn wir also in diesem Datenverzeichnis einen Wert haben, ist dies eine gültige .NET -Baugruppe, sonst ist dies nicht der Fall.

internal static class PortableExecutableHelper
{
    internal static bool IsDotNetAssembly(string peFile)
    {
        uint peHeader;
        uint peHeaderSignature;
        ushort machine;
        ushort sections;
        uint timestamp;
        uint pSymbolTable;
        uint noOfSymbol;
        ushort optionalHeaderSize;
        ushort characteristics;
        ushort dataDictionaryStart;
        uint[] dataDictionaryRVA = new uint[16];
        uint[] dataDictionarySize = new uint[16];


        Stream fs = new FileStream(peFile, FileMode.Open, FileAccess.Read);
        BinaryReader reader = new BinaryReader(fs);

        //PE Header starts @ 0x3C (60). Its a 4 byte header.
        fs.Position = 0x3C;

        peHeader = reader.ReadUInt32();

        //Moving to PE Header start location...
        fs.Position = peHeader;
        peHeaderSignature = reader.ReadUInt32();

        //We can also show all these value, but we will be       
        //limiting to the CLI header test.

        machine = reader.ReadUInt16();
        sections = reader.ReadUInt16();
        timestamp = reader.ReadUInt32();
        pSymbolTable = reader.ReadUInt32();
        noOfSymbol = reader.ReadUInt32();
        optionalHeaderSize = reader.ReadUInt16();
        characteristics = reader.ReadUInt16();

        /*
            Now we are at the end of the PE Header and from here, the
                        PE Optional Headers starts...
                To go directly to the datadictionary, we'll increase the      
                stream’s current position to with 96 (0x60). 96 because,
                        28 for Standard fields
                        68 for NT-specific fields
            From here DataDictionary starts...and its of total 128 bytes. DataDictionay has 16 directories in total,
            doing simple maths 128/16 = 8.
            So each directory is of 8 bytes.
                        In this 8 bytes, 4 bytes is of RVA and 4 bytes of Size.

            btw, the 15th directory consist of CLR header! if its 0, its not a CLR file :)
     */
        dataDictionaryStart = Convert.ToUInt16(Convert.ToUInt16(fs.Position) + 0x60);
        fs.Position = dataDictionaryStart;
        for (int i = 0; i < 15; i++)
        {
            dataDictionaryRVA[i] = reader.ReadUInt32();
            dataDictionarySize[i] = reader.ReadUInt32();
        }
        if (dataDictionaryRVA[14] == 0)
        {
            Console.WriteLine("This is NOT a valid CLR File!!");
            return false;
        }
        else
        {
            Console.WriteLine("This is a valid CLR File..");
            return true;
        }
        fs.Close();
    }
}

Ecma Ref, Blog Ref

Angesichts des gleichen Problems in der Vergangenheit habe ich Ihren Reflexionsansatz verwendet, da die Alternative darin besteht, den PE -Header manuell zu lesen so was. Ich schien für mein Szenario nur übertrieben zu sein, aber es kann für Sie nützlich sein.

Sie haben nicht angegeben, ob Sie dies in Code tun müssen oder ob Sie nur persönlich wissen müssen, ob eine Datei, die Sie in Ihrem System betrachten tun Sie dies). Wenn letztere, können Sie Dependenty Walker verwenden, um festzustellen, ob es eine Abhängigkeit von MSCOREE.DLL hat, der .NET -Laufzeit -Engine.

Sie könnten so etwas verwenden wie:

        AssemblyName assemblyName = null;

        try
        {
            assemblyName = AssemblyName.GetAssemblyName(filename);
        }
        catch (System.IO.FileNotFoundException ex)
        {
            throw new Exception("File not found!", ex);
        }
        catch (System.BadImageFormatException ex)
        {
            throw new Exception("File is not an .Net Assembly.", ex);
        }

Bitte überprüfen Sie auch: https://msdn.microsoft.com/en-us/library/ms173100.aspx

Sie können die ersten beiden Bytes aus der Datei lesen, wenn die Bytes "MZ" sind, dann versuchen Sie, den Montagennamen zu lesen, um zu bestimmen ((Microsoft Slow Way) Die Gültigkeit der Baugruppe.

    public static bool isValidAssembly (string sFileName)
    {
        try
        {
            using (FileStream fs = File.OpenRead(sFileName))
            {
                if ((fs.ReadByte() != 'M') || (fs.ReadByte() != 'Z'))
                {
                    fs.Close();
                    return false;
                }
                fs.Close();
            }

            // http://msdn.microsoft.com/en-us/library/ms173100.aspx
            object foo = SR.AssemblyName.GetAssemblyName(sFileName);
            return true;
        }
        catch 
        {
            return false;
        }
    }
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top