2008-11-06 21 views
269

Tengo una lista arbitraria de ensamblados .NET.¿Cómo determinar si se construyó un ensamblado .NET para x86 o x64?

Necesito comprobar programáticamente si cada DLL se construyó para x86 (a diferencia de x64 o cualquier CPU). es posible?

+0

posible duplicado de [¿Cómo puedo determinar para qué plataforma se compila un ejecutable?] (http://stackoverflow.com/questions/197951/how-can-i-determine-for-which- platform-an-executable-is-compiled) – nawfal

+2

Es posible que también desee consultar este: [check-if-unmanaged-dll-is-32-bit-or-64-bit] (http://stackoverflow.com/questions/1001404/check-if-unmanaged-dll-is-32-bit-or-64-bit). – Matt

+2

En la versión posterior de CorFlags, correspondiente a .NET 4.5, ["32BIT" fue reemplazado por "32BITREQ" y "32BITPREF".] (Http://stackoverflow.com/questions/18608785/how-to-interpret-the- corflags-flags/23614024 # 23614024). –

Respuesta

213

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

Puede examinar los metadatos de montaje de la instancia AssemblyName devuelto:

Usando 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 plataforma de destino.

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

+52

Perdona la pregunta estúpida, pero ¿qué te dice esto que es x86? –

+46

El campo Arquitectura de procesador es una enumeración; en el ejemplo anterior, está configurado en MSIL, lo que significa "Neutral con respecto al procesador y bits por palabra". Otros valores incluyen X86, IA64, Amd64. Ver http://msdn.microsoft.com/en-us/library/system.reflection.processorarchitecture.aspx para más detalles. –

+0

Recibo el siguiente error al intentar usar PowerShell: 'Llamada de excepción" GetAssemblyName "con" 1 "argumento (s):" No se pudo cargar el archivo o ensamblado '[DLLName] .dll' o una de sus dependencias. El sistema no puede encontrar el archivo especificado. "' (Sí, lo deletreé correctamente). – PeterX

202

Puede usar la herramienta CorFlagsCLI (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 apertura un conjunto como un activo binaria que debe ser capaz de determinar dónde tiene que tratar de determinar si el indicador 32BIT se establece en 1 (x 86) 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 x64 Development with .NET tiene alguna información sobre corflags.

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

+1

Después de ver su actualización, usar GetPEKind parece ser la forma correcta de hacerlo. He marcado el tuyo como la respuesta. –

+0

Excelente consejo sobre Module.GetPEKind, nunca lo supimos hasta ahora. Siempre he usado la herramienta 'corflags'. –

+8

GetPEKind falla en un proceso de 64 bits al verificar conjuntos de 32 bits – jjxtra

125

Solo para aclaración, CorFlags.exe es parte de .NET Framework SDK. Tengo las herramientas de desarrollo en mi máquina, y la forma más sencilla para mí determinar si un archivo DLL es sólo de 32 bits es:

  1. Abra el Visual Studio de comandos (en Windows: menú Inicio/Programas/Microsoft visual Studio/visual Studio Tools/visual Studio 2008 Command Prompt)

  2. CD en el directorio que contiene el archivo DLL en cuestión

  3. corflags ejecuta de la siguiente: corflags MyAssembly.DLL

obtendrá algo salida como esta:

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 

De acuerdo con los comentarios de las banderas más arriba se van a leer de la siguiente manera:

  • Cualquier CPU: PE = PE32 y 32BIT = 0
  • x86: PE = PE32 y 32BIT = 1
  • 64-bit: PE = PE32 + y 32BIT = 0
+9

Incorrecto. 0 = Cualquier CPU, no 2 –

+9

Esto parece haber cambiado mientras tanto; corflags ahora muestra '32BITREQ' y' 32BITPREF' en lugar de un único valor '32BIT'. –

+1

Microsoft .NET 4.5 introdujo una nueva opción, Cualquier CPU de 32 bits Preferido. [Aquí] (http://stackoverflow.com/a/23614024/465053) son los detalles. – RBT

1

Otra forma de comprobar la plataforma de destino de un ensamblado de .NET está inspeccionando el conjunto con .NET Reflector ...

@ # ~ # ~ €! ¡Me acabo de dar cuenta de que la nueva versión no es gratis! Entonces, corrección, si tiene una versión gratuita de .NET reflector, puede usarla para verificar la plataforma de destino.

+9

Utilice [ILSpy] (http://wiki.sharpdevelop.net/ILSpy.ashx), es una aplicación básica de código abierto que hace las mismas cosas que Reflector –

17

¿Qué tal si solo te escribes? El núcleo de la arquitectura PE no ha sido cambiado en serio desde su implementación en Windows 95. He aquí 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. 

Sin embargo, con este método que permite para las posibilidades de nuevas constantes, simplemente valide la devolución como mejor le parezca.

+1

Interesante, gracias por el código con la explicación. Module.GetPEKind es probablemente la ruta más fácil. Pero esto es útil para aprender. Gracias. –

+2

Muy interesante, pero cuando tengo una aplicación compilada con Cualquier CPU, el resultado es 0x10B. Esto es incorrecto porque mi aplicación se ejecuta en un sistema x64. ¿Hay alguna otra bandera para verificar? – Samuel

+0

GetPEArchitecture funciona para ensamblados compilados con .net 3.5, 4.0, 4.5 y 4.5.1? De todos modos, creo, Module.GetPEKind falla en un proceso de 64 bits cuando se comprueban ensamblajes de 32 bits. – Kiquenet

9

Intente utilizar CorFlagsReader from this project at CodePlex. No tiene referencias a otros ensambles y puede usarse tal cual.

+1

Esta es la respuesta más precisa y útil. –

+0

El enlace sigue funcionando a partir de este escrito, pero como CodePlex está a punto de cerrarse, sería bueno realizar la acción adecuada antes de que sea demasiado tarde. –

5
[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); 
    } 
} 
+0

Gracias por esto, una de nuestras aplicaciones debe ser construida como x86, agregar una prueba de unidad asegura que las bibliotecas de compilación del servidor de compilación serán de 32 bits y evita que esos errores ocurran :) – Mido

3

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

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

Esto supone que corflags.exe está en el %PATH%.La forma más sencilla de garantizar esto es usar un Developer Command Prompt. Alternativamente, puede copiarlo de default location.

Si el archivo por lotes a continuación está dirigido contra un administrado dll o exe, se mostrará de forma incorrecta como x86, ya que la salida real de Corflags.exe será un mensaje de error similar al siguiente:

corflags : error CF008 : The specified file does not have a valid managed header

@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. 
1

Una aplicación más avanzada para que pueda 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 
1

una forma más sería utilizar dumpbin de las herramientas de Visual Studio en DLL y buscar la salida apropiada

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: Por encima de O/P es para la DLL de 32 bits

Uno más útil opción con Dumpbin.exe está/EXPORTACIONES, se le mostrará la función expuesta por el DLL

dumpbin.exe /EXPORTS <PATH OD THE DLL> 
2

dotPeek de JetBrians proporciona una forma rápida y fácil de ver msil (Cualquier CPU), x86, x64 dotPeek

Cuestiones relacionadas