¿Cómo puedo determinar si un ensamblado .NET se creó para x86 o x64?
Tengo una lista arbitraria de ensamblados .NET.
Necesito verificar mediante programación si cada DLL se creó para x86 (a diferencia de x64 o cualquier CPU). es posible?
Mira a System.Reflection.AssemblyName.GetAssemblyName(string assemblyFile)
.
Puede examinar los metadatos del ensamblado de la instancia de AssemblyName devuelta:
Usando PowerShell :
[36] C:\> [reflection.assemblyname]::GetAssemblyName("${pwd}\Microsoft.GLEE.dll") | Florida Nombre : Microsoft.GLEE Versión: 1.0.0.0 Información cultural: CodeBase: archivo:///C:/projects/powershell/BuildAnalyzer/... EscapedCodeBase: archivo:///C:/projects/powershell/BuildAnalyzer/... Arquitectura del procesador: MSIL Banderas: clave pública Algoritmo Hash: SHA1 Compatibilidad de versiones: Misma máquina Par de claves : Nombre completo: Microsoft.GLEE, Versión=1.0.0.0, Cultura=neut...
Aquí, ProcessorArchitecture identifica la plataforma de destino.
- Amd64 : Un procesador de 64 bits basado en la arquitectura x64.
- Arm : Un procesador ARM.
- IA64 : procesador Intel Itanium de 64 bits únicamente.
- MSIL : Neutral respecto al procesador y bits por palabra.
- X86 : Un procesador Intel de 32 bits, ya sea nativo o en el entorno Windows sobre Windows en una plataforma de 64 bits ( WoW64 ).
- Ninguno : combinación desconocida o no especificada de procesador y bits por palabra.
Estoy usando PowerShell en este ejemplo para llamar al método.
Puede utilizar la herramienta CLI de CorFlags (por ejemplo, C:\Program Files\Microsoft SDKs\Windows\v7.0\Bin\CorFlags.exe) para determinar el estado de un ensamblaje, en función de su salida y abrir un ensamblaje como activo binario, debería poder determinar dónde debe buscar para determinar si el indicador de 32 bits está configurado en 1 ( x86 ) o 0 ( cualquier CPU o x64 , dependiendo de ):PE
Option | PE | 32BIT
----------|-------|---------
x86 | PE32 | 1
Any CPU | PE32 | 0
x64 | PE32+ | 0
La publicación del blog Desarrollo x64 con .NET tiene información sobre corflags
.
Aún mejor, puede usarloModule.GetPEKind
para determinar si un ensamblaje tiene PortableExecutableKinds
valor PE32Plus
(64 bits), Required32Bit
(32 bits y WoW ) o ILOnly
(cualquier CPU) junto con otros atributos.
Solo como aclaración, CorFlags.exe es parte del SDK de .NET Framework . Tengo las herramientas de desarrollo en mi máquina y la forma más sencilla para mí de determinar si una DLL es solo de 32 bits es:
Abra el símbolo del sistema de Visual Studio (en Windows: menú Inicio/Programas/Microsoft Visual Studio/Visual Studio Tools/Símbolo del sistema de Visual Studio 2008)
CD al directorio que contiene la DLL en cuestión
Ejecute corflags como este:
corflags MyAssembly.dll
Obtendrá un resultado similar a este:
Microsoft (R) .NET Framework CorFlags Conversion Tool. Version 3.5.21022.8
Copyright (c) Microsoft Corporation. All rights reserved.
Version : v2.0.50727
CLR Header: 2.5
PE : PE32
CorFlags : 3
ILONLY : 1
32BIT : 1
Signed : 0
Según los comentarios, las banderas anteriores deben leerse de la siguiente manera:
- Cualquier CPU: PE = PE32 y 32BIT = 0
- x86: PE = PE32 y 32 BITS = 1
- 64 bits: PE = PE32+ y 32 bits = 0
Simplemente escribe el tuyo. El núcleo de la arquitectura PE no ha cambiado seriamente desde su implementación en Windows 95 .
Aquí hay un ejemplo de C#:
public static ushort GetPEArchitecture(string pFilePath)
{
ushort architecture = 0;
try
{
using (System.IO.FileStream fStream = new System.IO.FileStream(pFilePath, System.IO.FileMode.Open, System.IO.FileAccess.Read))
{
using (System.IO.BinaryReader bReader = new System.IO.BinaryReader(fStream))
{
// Check the MZ signature
if (bReader.ReadUInt16() == 23117)
{
// Seek to e_lfanew.
fStream.Seek(0x3A, System.IO.SeekOrigin.Current);
// Seek to the start of the NT header.
fStream.Seek(bReader.ReadUInt32(), System.IO.SeekOrigin.Begin);
if (bReader.ReadUInt32() == 17744) // Check the PE\0\0 signature.
{
// Seek past the file header,
fStream.Seek(20, System.IO.SeekOrigin.Current);
// Read the magic number of the optional header.
architecture = bReader.ReadUInt16();
}
}
}
}
}
catch (Exception) { /* TODO: Any exception handling you want
to do, personally I just take 0
as a sign of failure */
}
// If architecture returns 0, there has been an error.
return architecture;
}
}
Ahora las constantes actuales son:
0x10B - PE32 format.
0x20B - PE32+ format.
Pero con este método se permiten las posibilidades de nuevas constantes. Simplemente valida la devolución como mejor te parezca.