Pregunta

¿Cuál es la mejor manera de comprobar si un archivo DLL es una DLL de Win32 o si se trata de un montaje de CLR. En el momento en que utilizo este código

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

Pero me gusta comprobar antes de la carga, porque no quiero que esas excepciones (tiempo).

¿Hay una mejor manera?

¿Fue útil?

Solución

Comprobar la cabecera PE:

  

cabecera DOS comienza en 0x0, el valor DWORD en   0x3C contiene un puntero al PE   firma (normalmente 0x80) que es 4   bytes, los próximos 20 bytes es la COFF   encabezado y entonces no es la cabecera PE   (En 0x9. El encabezado de PE es de 224 bytes   y contiene el directorio de datos (al 96   bytes en la cabecera PE = 0xf. los   entrada 15a (en 0x16 es el encabezado CLR   descriptor (a veces llamado el COM   descriptor, pero esto no tiene   nada que ver con COM). Si esto es   vacía (es decir, 0 en los 8 bytes de 0x168   a 0x16f), entonces el archivo no es un .NET   montaje. Si desea comprobar si   es una DLL COM entonces usted debe buscar a   ver si se exporta GetClassObject.

Ref.

Actualizar : hay una manera más '.NET' para lograrlo:

Module.GetPEKind método y comprobar el PortableExecutableKinds enumeración:

  

NotAPortableExecutableImage El archivo no está en portable ejecutable   (PE) formato de archivo.

     

ILOnly El ejecutable sólo contiene lenguaje intermedio de Microsoft   (MSIL), y es por lo tanto neutral con   respecto a plataformas de 32 bits o de 64 bits.

     

Required32Bit El ejecutable se puede ejecutar en una plataforma de 32 bits, o en el   Windows de 32 bits en Windows (WOW)   ambiente en una plataforma de 64 bits.

     

PE32Plus El ejecutable requiere una plataforma de 64 bits.

     

Unmanaged32Bit El ejecutable contiene código no administrado puro.

Otros consejos

Si un ensamblado se carga por ejemplo Assembly.LoadFile(dotNetDllorExe) y no lanza ninguna excepción, es un ensamblado de .NET válido. Si no es así, entonces va a lanzar una “BadImageFormatException”.

La idea de controlar el clima es un archivo de ensamblaje o no cargándolo y comprobando si excepción se emite o no; no parece ser demasiado limpio. Después se supone que todas las excepciones que se utilizará en casos excepcionales.


NET son archivos regulares Win32 PE, el sistema operativo no diferenciar entre NET y Win32 binarios ejecutables, que son los mismos archivos PE normales. Entonces, ¿cómo funciona el sistema si un DLL o EXE es un ensamblado administrado con el fin de cargar el CLR?

Se valida el encabezado del archivo para comprobar si se trata de un ensamblado administrado o no. En el ECMA Especificaciones partición II - Metadatos que se envía junto con el SDK de .NET que se ve hay una cabecera separada de la CLI en el formato PE. Es el directorio 15a de datos en el PE Opcional encabezados . Por lo tanto, en términos simples, si tenemos valor en este directorio de datos, entonces significa que este es un ensamblado de .NET válida, de lo contrario no lo es.

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

Ante el mismo problema en el pasado, he recurrido a la utilización de su enfoque de la reflexión, porque la alternativa es leer manualmente la cabecera PE como esto . Nos pareció que era excesivo para mi escenario, pero puede ser útil para usted.

No se especificó si se tiene que hacer esto en el código, o si lo que personalmente necesita saber si un archivo que está viendo en su sistema es un ensamblado de .NET (que tal vez usted piensa que requiere que la escritura de su el propio código para hacerlo). En este último caso, puede utilizar Dependency Walker para ver si tiene una dependencia en Mscoree.dll, que es el motor de tiempo de ejecución .Net.

Se podría utilizar algo como:

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

Por favor, también echa un vistazo: https://msdn.microsoft.com/en -us / biblioteca / ms173100.aspx

  

Puede leer los dos primeros bytes del archivo, si los bytes son "MZ" y luego tratar de leer el nombre de ensamblado para determinar ( Microsoft manera lenta) la validez del conjunto.

    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;
        }
    }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top