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í, arrojará una "BadImageFormatException".
La idea de verificar el estado del tiempo de un archivo es ensamblarlo o no cargándolo y verificando si se produce una excepción o no; no parece estar muy limpio Después de todas las excepciones se supone que se utilizarán excepcionalmente.
Los ensamblados .NET son archivos regulares de Win32 PE, el sistema operativo no distingue entre ensamblados .NET y archivos binarios ejecutables de Win32, son los mismos archivos PE normales. Entonces, ¿cómo funciona el sistema si un DLL o EXE es un ensamblado administrado para cargar el CLR?
Valida el encabezado del archivo para comprobar si se trata de un ensamblaje administrado o no. En la Partición II de Especificaciones de ECMA - Metadatos que se envía junto con .NET SDK, verá que hay un encabezado de CLI por separado en el Formato de PE. Es el 15º directorio de datos en los encabezados opcionales PE. Entonces, en términos simples, si tenemos valor en este directorio de datos, significa que este es un ensamblado .NET válido, 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
que estoy tratando de hacer algo similar a la OP. Esta solución suena genial, pero ¿cómo se puede obtener una instancia del Módulo sin llamar a Assembly.LoadFile (que arroja una BadImageFormatException para dlls que no son CLR antes de poder llamar a GetPEKind)? –
@Simon: por supuesto, si es de su interés, ¿qué tal si escribe y agrega algún código como respuesta? –
@Mitch: Ok tal vez el voto negativo fue un poco apresurado. Traté de deshacerlo, pero el tiempo de espera ha transcurrido. Lo siento. no dude en rechazar algunas de mis respuestas :). Intenté que esto funcionara. Aunque me pareció que la pregunta de Pauls era válida. Module.GetPEKind es instancia. Entonces, para obtener un Módulo, debe llamar al ensamblaje Assembly.Load. que lanzará una excepción. Dado que la pregunta explícitamente dice "sin excepciones", parecería que esta respuesta es incompleta o incorrecta. – Simon