.net assemblies x86 64bit x86-64

¿Cómo determinar si un ensamblado.NET fue construido para x86 o x64?



assemblies 64bit (14)

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?


¿Qué tal si solo escribes tu propia propiedad? El núcleo de la arquitectura de 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)) { if (bReader.ReadUInt16() == 23117) //check the MZ signature { fStream.Seek(0x3A, System.IO.SeekOrigin.Current); //seek to e_lfanew. fStream.Seek(bReader.ReadUInt32(), System.IO.SeekOrigin.Begin); //seek to the start of the NT header. if (bReader.ReadUInt32() == 17744) //check the PE/0/0 signature. { fStream.Seek(20, System.IO.SeekOrigin.Current); //seek past the file header, architecture = bReader.ReadUInt16(); //read the magic number of the optional header. } } } } } 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 permite las posibilidades de nuevas constantes, solo valide la devolución como mejor le parezca.


A continuación se muestra un archivo por lotes que ejecutará corflags.exe en todos los dlls corflags.exe y exes en el directorio de trabajo actual y en todos los subdirectorios, analiza los resultados y muestra la arquitectura de destino de cada uno.

Dependiendo de la versión de corflags.exe que se use, los artículos de línea en la salida incluirán 32BIT o 32BITREQ (y 32BITPREF ). Cualquiera de estos dos incluidos en la salida es la línea de pedido crítica que debe verificarse para diferenciar entre Any CPU y x86 . Si está utilizando una versión anterior de corflags.exe (anterior a Windows SDK v8.0A), solo estará presente la línea de pedido de 32BIT en la salida, como han indicado otros en respuestas anteriores. De 32BITREQ contrario, 32BITREQ y 32BITPREF reemplazan.

Esto supone que corflags.exe está en el %PATH% . La forma más sencilla de garantizar esto es utilizar un Developer Command Prompt . Alternativamente, podría copiarlo desde su ubicación predeterminada .

Si el archivo por lotes a continuación se ejecuta en una dll o exe no administrada, se mostrará incorrectamente como x86 , ya que la salida real de Corflags.exe será un mensaje de error similar a:

corflags: error CF008: el archivo especificado no tiene un encabezado administrado válido

@echo off echo. echo Target architecture for all exes and dlls: echo. REM For each exe and dll in this directory and all subdirectories... for %%a in (.exe, .dll) do forfiles /s /m *%%a /c "cmd /c echo @relpath" > testfiles.txt for /f %%b in (testfiles.txt) do ( REM Dump corflags results to a text file corflags /nologo %%b > corflagsdeets.txt REM Parse the corflags results to look for key markers findstr /C:"PE32+">nul ./corflagsdeets.txt && ( REM `PE32+` indicates x64 echo %%~b = x64 ) || ( REM pre-v8 Windows SDK listed only "32BIT" line item, REM newer versions list "32BITREQ" and "32BITPREF" line items findstr /C:"32BITREQ : 0">nul /C:"32BIT : 0" ./corflagsdeets.txt && ( REM `PE32` and NOT 32bit required indicates Any CPU echo %%~b = Any CPU ) || ( REM `PE32` and 32bit required indicates x86 echo %%~b = x86 ) ) del corflagsdeets.txt ) del testfiles.txt echo.


DotPeek de JetBrians proporciona una manera rápida y fácil de ver msil (anycpu), x86, x64


Forma más genérica: use la estructura de archivos para determinar el bitness y el tipo de imagen:

public static CompilationMode GetCompilationMode(this FileInfo info) { if (!info.Exists) throw new ArgumentException($"{info.FullName} does not exist"); var intPtr = IntPtr.Zero; try { uint unmanagedBufferSize = 4096; intPtr = Marshal.AllocHGlobal((int)unmanagedBufferSize); using (var stream = File.Open(info.FullName, FileMode.Open, FileAccess.Read)) { var bytes = new byte[unmanagedBufferSize]; stream.Read(bytes, 0, bytes.Length); Marshal.Copy(bytes, 0, intPtr, bytes.Length); } //Check DOS header magic number if (Marshal.ReadInt16(intPtr) != 0x5a4d) return CompilationMode.Invalid; // This will get the address for the WinNT header var ntHeaderAddressOffset = Marshal.ReadInt32(intPtr + 60); // Check WinNT header signature var signature = Marshal.ReadInt32(intPtr + ntHeaderAddressOffset); if (signature != 0x4550) return CompilationMode.Invalid; //Determine file bitness by reading magic from IMAGE_OPTIONAL_HEADER var magic = Marshal.ReadInt16(intPtr + ntHeaderAddressOffset + 24); var result = CompilationMode.Invalid; uint clrHeaderSize; if (magic == 0x10b) { clrHeaderSize = (uint)Marshal.ReadInt32(intPtr + ntHeaderAddressOffset + 24 + 208 + 4); result |= CompilationMode.Bit32; } else if (magic == 0x20b) { clrHeaderSize = (uint)Marshal.ReadInt32(intPtr + ntHeaderAddressOffset + 24 + 224 + 4); result |= CompilationMode.Bit64; } else return CompilationMode.Invalid; result |= clrHeaderSize != 0 ? CompilationMode.CLR : CompilationMode.Native; return result; } finally { if (intPtr != IntPtr.Zero) Marshal.FreeHGlobal(intPtr); } }

Enumeración de modo compilación

[Flags] public enum CompilationMode { Invalid = 0, Native = 0x1, CLR = Native << 1, Bit32 = CLR << 1, Bit64 = Bit32 << 1 }

Código fuente con explicación en GitHub




Otra forma de verificar la plataforma de destino de un ensamblado .NET es inspeccionar el ensamblaje con .NET Reflector ...

@ # ~ # € ~! ¡Acabo de darme cuenta de que la nueva versión no es gratis! Por lo tanto, corrección, si tiene una versión gratuita de .NET reflector, puede usarla para verificar la plataforma de destino.


Puede usar la herramienta CLI CorFlags (por ejemplo, C: / Archivos de programa / Microsoft SDKs / Windows / v7.0 / Bin / CorFlags.exe) para determinar el estado de un ensamblaje, en función de su salida y de abrir un ensamblaje como un activo binario debe poder determinar dónde debe buscar determinar si el indicador de 32 BIT está establecido en 1 ( x86 ) o 0 ( cualquier CPU o x64 , según el PE ):

Option | PE | 32BIT ----------|-------|--------- x86 | PE32 | 1 Any CPU | PE32 | 0 x64 | PE32+ | 0

La publicación del blog x64 Development con .NET tiene alguna información sobre corflags .

Aún mejor, puede usar Module.GetPEKind para determinar si un ensamblaje es PortableExecutableKinds valor PE32Plus (64 bits), Required32Bit (32 bits y WOW), o ILOnly (cualquier CPU) junto con otros atributos.


Solo para aclarar, 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 solo es de 32 bits es:

  1. Abra el Símbolo del sistema de Visual Studio (En Windows: menú Inicio / Programas / Microsoft Visual Studio / Visual Studio Tools / Visual Studio 2008 Símbolo del sistema)

  2. CD al directorio que contiene la DLL en cuestión

  3. Ejecute corflags como este: corflags MyAssembly.dll

Obtendrá salida algo como esto:

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 de arriba deben leerse como sigue:

  • Cualquier CPU: PE = PE32 y 32BIT = 0
  • x86: PE = PE32 y 32BIT = 1
  • 64 bits: PE = PE32 + y 32BIT = 0

Una aplicación más avanzada que puedes encontrar aquí: CodePlex - ApiChange

Ejemplos:

C:/Downloads/ApiChange>ApiChange.exe -CorFlags c:/Windows/winhlp32.exe File Name; Type; Size; Processor; IL Only; Signed winhlp32.exe; Unmanaged; 296960; X86 C:/Downloads/ApiChange>ApiChange.exe -CorFlags c:/Windows/HelpPane.exe File Name; Type; Size; Processor; IL Only; Signed HelpPane.exe; Unmanaged; 733696; Amd64


Una forma más sería usar dumpbin de las herramientas de Visual Studio en DLL y buscar el resultado apropiado

dumpbin.exe /HEADERS <your dll path> FILE HEADER VALUE 14C machine (x86) 4 number of sections 5885AC36 time date stamp Mon Jan 23 12:39:42 2017 0 file pointer to symbol table 0 number of symbols E0 size of optional header 2102 characteristics Executable 32 bit word machine DLL

Nota: encima de / p es para 32bit dll

Una opción más útil con dumpbin.exe es / EXPORTS, le mostrará la función expuesta por el dll

dumpbin.exe /EXPORTS <PATH OF THE DLL>


cfeduke señala la posibilidad de llamar a GetPEKind. Es potencialmente interesante hacer esto desde PowerShell.

Aquí, por ejemplo, hay un código para un cmdlet que se podría usar: https://.com/a/16181743/64257

Alternativamente, en https://.com/a/4719567/64257 se observa que "también está el cmdlet Get-PEHeader en las extensiones de la comunidad de PowerShell que se puede usar para probar imágenes ejecutables".


Mire System.Reflection.AssemblyName.GetAssemblyName(string assemblyFile)

Puede examinar los metadatos del conjunto desde la instancia de AssemblyName devuelta:

Utilizando PowerShell :

[36] C:/> [reflection.assemblyname]::GetAssemblyName("${pwd}/Microsoft.GLEE.dll") | fl Name : Microsoft.GLEE Version : 1.0.0.0 CultureInfo : CodeBase : file:///C:/projects/powershell/BuildAnalyzer/... EscapedCodeBase : file:///C:/projects/powershell/BuildAnalyzer/... ProcessorArchitecture : MSIL Flags : PublicKey HashAlgorithm : SHA1 VersionCompatibility : SameMachine KeyPair : FullName : Microsoft.GLEE, Version=1.0.0.0, Culture=neut...

Aquí, ProcessorArchitecture identifica la plataforma de destino.

  • Amd64 : un procesador de 64 bits basado en la arquitectura x64.
  • Brazo : Un procesador ARM.
  • IA64 : Un procesador Intel Itanium de 64 bits solamente.
  • MSIL : Neutral con respecto al procesador y bits por palabra.
  • X86 : un procesador Intel de 32 bits, ya sea nativo o en el entorno Windows en Windows en una plataforma de 64 bits (WOW64).
  • Ninguno : una combinación desconocida o no especificada de procesador y bits por palabra.

Estoy usando PowerShell en este ejemplo para llamar al método.


[TestMethod] public void EnsureKWLLibrariesAreAll64Bit() { var assemblies = Assembly.GetExecutingAssembly().GetReferencedAssemblies().Where(x => x.FullName.StartsWith("YourCommonProjectName")).ToArray(); foreach (var assembly in assemblies) { var myAssemblyName = AssemblyName.GetAssemblyName(assembly.FullName.Split('','')[0] + ".dll"); Assert.AreEqual(ProcessorArchitecture.MSIL, myAssemblyName.ProcessorArchitecture); } }