Question

Quelle est la meilleure façon de vérifier si un fichier DLL est une DLL Win32 ou si elle est un ensemble de CLR. En ce moment j'utilise ce 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;
    }

Mais je tiens à vérifier avant le chargement parce que je ne veux pas que ces exceptions (temps).

Y at-il une meilleure façon?

Était-ce utile?

La solution

Vérifiez l'en-tête PE:

  

En-tête DOS commence à 0x0, DWORD à   0x3c contient un pointeur vers le PE   signature (habituellement 0x80) qui est 4   octets, 20 octets suivants est le COFF   En-tête et puis il y a l'en-tête PE   (À 0x9. L'en-tête PE est de 224 octets   et contient le répertoire de données (96   octets dans l'en-tête PE = 0xf. le   15e entrée (à 0x16 est l'en-tête CLR   descripteur (parfois appelé COM   descripteur, mais cela n'a pas   rien à voir avec COM). Si c'est   vide (soit 0 dans les 8 octets de 0x168   à 0x16f) le fichier est pas un .NET   Assemblée. Si vous voulez vérifier si   est une DLL COM alors vous devriez chercher à   voir si elle exporte GetClassObject.

Ref.

UPDATE : il y a une manière plus '.NET' d'accomplir ceci:

Utilisez Module.GetPEKind procédé et vérifier la PortableExecutableKinds Enumeration:

  

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

     

ILONLY L'exécutable ne contient que Microsoft intermediate   (MSIL), et est donc neutre   rapport à 32 bits ou les plates-formes 64 bits.

     

Required32Bit Le fichier exécutable peut être exécuté sur une plate-forme 32 bits, ou en   Windows on Windows (WOW) 32 bits   environnement sur une plate-forme 64 bits.

     

PE32Plus Le fichier exécutable nécessite une plate-forme 64 bits.

     

Unmanaged32Bit Le fichier exécutable contient pur code non géré.

Autres conseils

Si un assemblage se charge par exemple Assembly.LoadFile(dotNetDllorExe) et ne jette pas une exception, il est un ensemble de .NET valide. Si ce n'est pas alors il va lancer une « BadImageFormatException ».

L'idée de vérifier la météo est un fichier assemblage ou non en chargeant et vérifier si exception est levée ou non; ne semble pas être trop propre. Après toutes les exceptions sont censées être utilisées exceptionnellement.


ensembles .NET sont régulièrement des fichiers PE Win32, le système d'exploitation ne fait pas de distinction entre les ensembles .NET et les binaires exécutables Win32, ils sont les mêmes fichiers PE normaux. Alors, comment le système fonctionne si une DLL ou EXE est un ensemble géré afin de charger le CLR?

Il valide l'en-tête de fichier pour vérifier si elle est un assemblage géré ou non. Dans le ECMA Caractéristiques Partition II - Métadonnées qui est livré avec le SDK .NET que vous voyez il y a une tête séparée CLI dans le format PE. Il est le 15 répertoire de données dans les en-têtes PE en option . Donc, en termes simples, si nous avons la valeur dans ce répertoire de données, cela signifie que c'est un ensemble de .NET valide, sinon ce n'est pas.

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 Réf

Face au même problème dans le passé, j'ai eu recours à l'utilisation de votre approche de réflexion parce que l'alternative est de lire manuellement l'en-tête PE comme celui-ci . Tout semblait exagéré pour mon scénario, mais il peut être utile pour vous.

Vous ne précise pas si vous devez le faire dans le code, ou si vous avez juste besoin personnellement de savoir si un fichier que vous regardez sur votre système est un ensemble de .NET (que vous pensez peut-être vous oblige à écrire votre propre code pour le faire). Dans ce dernier cas, vous pouvez utiliser Dependency Walker pour voir si elle a une dépendance à l'égard MSCorEE.dll, qui est le moteur d'exécution .Net.

Vous pouvez utiliser quelque chose comme:

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

S'il vous plaît vérifier aussi: https://msdn.microsoft.com/en -nous / bibliothèque / ms173100.aspx

  

Vous pouvez lire les deux premiers octets du fichier, si les octets sont « MZ » essayez de lire le nom de l'assemblage pour déterminer ( manière lente microsoft ) la validité de l'assemblée.

    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;
        }
    }
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top