Comment déterminer si a.NET l'assemblage a été construit pour x86 ou x64?

j'ai une liste arbitraire d'assemblages .NET.

je dois programmatiquement vérifier si chaque DLL a été construit pour x86 (par opposition à x64 ou tout CPU). Est-ce possible?

286
demandé sur Peter Mortensen 2008-11-07 01:14:03

14 réponses

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

vous pouvez examiner les métadonnées d'assemblage à partir de L'instance de retour du nom D'assemblage:

Utilisant 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... 

ici, ProcessorArchitecture identifie la plate-forme cible.

J'utilise PowerShell dans cet exemple pour appeler la méthode.

236
répondu x0n 2016-09-28 10:08:10

vous pouvez utiliser le CorFlags 1519110920" CLI outil (par exemple, C:\Program fichiers\Microsoft SDKs\Windows\v7.0 \ Bin\CorFlags.exe) pour déterminer le statut d'un assemblage, basé sur sa sortie et l'ouverture d'un assemblage en tant qu'actif binaire, vous devriez être en mesure de déterminer où vous devez chercher à déterminer si le drapeau 32BIT est fixé à 1 ( x86 ) ou 0 ( N'importe quel CPU ou x64 , selon PE ):

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

le billet de blog x64 développement avec .NET a quelques informations sur corflags .

encore mieux, vous pouvez utiliser Module.GetPEKind pour déterminer si un assemblage est PortableExecutableKinds valeur PE32Plus (64 bits), Required32Bit (32 bits et WOW), ou ILOnly (tout CPU) avec d'autres attributs.

211
répondu cfeduke 2015-06-28 13:24:55

juste pour clarifier, CorFlags.exe fait partie du .net Framework SDK . J'ai les outils de développement sur ma machine, et le moyen le plus simple pour moi de déterminer si une DLL est 32-bit seulement est de:

  1. ouvrir L'invite de commande Visual Studio (dans Windows: menu Start/Programs/Microsoft Visual Studio/Visual Studio Tools/Visual Studio 2008)

  2. CD à l' répertoire contenant la DLL en question

  3. Exécuter corflags comme ceci: corflags MyAssembly.dll

vous obtiendrez une sortie de ce genre:

    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

selon les commentaires, les drapeaux ci-dessus doivent être lus comme suit:

  • tout CPU: PE = PE32 et 32BIT = 0
  • x86: PE = PE32 et 32BIT = 1
  • 64 bits: PE = PE32+ et 32BIT = 0
130
répondu JoshL 2018-03-15 08:18:11

et si tu écrivais toi-même? Le cœur de l'architecture PE n'a pas été sérieusement modifié depuis sa mise en œuvre dans Windows 95. Voici un exemple 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"151900920""151900920" 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;
    }
}

maintenant les constantes actuelles sont:

0x10B - PE32  format.
0x20B - PE32+ format.

mais avec cette méthode il permet les possibilités de nouvelles constantes, il suffit de valider le retour comme vous le souhaitez.

17
répondu Jason 2012-03-19 09:31:37

Essayez d'utiliser CorFlagsReader de ce projet sur CodePlex . Il ne fait pas référence à d'autres assemblages et peut être utilisé tel quel.

9
répondu Ludwo 2013-02-18 12:45:49
[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);
    }
}
6
répondu Morgan Mellor 2013-09-26 18:24:20

ci-dessous est un fichier batch qui va exécuter corflags.exe contre tous dlls et exes dans le répertoire courant de travail et tous les sous-répertoires, analyser les résultats et afficher l'architecture cible de chacun.

selon la version de corflags.exe qui est utilisée, les lignes dans la sortie sera soit 32BIT , ou 32BITREQ (et 32BITPREF ). Celui de ces deux est inclus dans la sortie est l'élément critique qui doit être vérifié pour faire la différence entre Any CPU et x86 . Si vous utilisez une ancienne version de corflags.exe (pre Windows SDK v8.0A), alors seule la ligne 32BIT sera présente dans la sortie, comme d'autres l'ont indiqué dans des réponses antérieures. Sinon 32BITREQ et 32BITPREF le remplacent.

cela suppose que corflags.exe est dans le %PATH% . La façon la plus simple d'y parvenir est d'utiliser un Developer Command Prompt . Vous pouvez également le copier à partir de son emplacement par défaut .

si le fichier de lot ci-dessous est exécuté contre un dll ou exe non géré , il s'affichera incorrectement comme x86 , puisque la sortie réelle de Corflags.exe sera un message d'erreur similaire à:

corflags: error CF008 : le fichier spécifié n'a pas d'en-tête géré valide

@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.
4
répondu Eric Lease 2017-05-23 10:31:17

DotPeek de JetBrians fournit un moyen rapide et facile de voir msil(anycpu), x86, x64 dotPeek

4
répondu Prabhakaran Rajagopal 2017-08-22 07:20:43

une autre façon de vérifier la plate-forme cible d'un ensemble .NET consiste à inspecter l'ensemble avec un réflecteur .NET ...

@#~#€~! Je viens de réaliser que la nouvelle version n'est pas gratuit! Donc, correction, si vous avez une version gratuite de .net reflector, vous pouvez l'utiliser pour vérifier la plateforme cible.

1
répondu juanjo.arana 2013-02-14 09:30:10

cfeduke note la possibilité d'appeler GetPEKind. C'est potentiellement intéressant de faire ça de PowerShell.

ici, par exemple, est le code pour un cmdlet qui pourrait être utilisé: https://stackoverflow.com/a/16181743/64257

Sinon, à https://stackoverflow.com/a/4719567/64257 il est noté que "il y a aussi le PEHeader applet de commande dans le PowerShell Communauté Extensions qui peut être utilisé pour tester exécutable images."

1
répondu Chris 2017-05-23 11:54:50

une application plus avancée pour que vous pouvez trouver ici: CodePlex-ApiChange

exemples:

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
répondu Wernfried Domscheit 2016-10-04 12:12:36

une autre façon serait d'utiliser dumpbin à partir des outils Visual Studio sur DLL et de chercher la sortie appropriée

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

Note: au-dessus de o / p est pour dll 32bit

une autre option utile avec dumpbin.exe is / EXPORTS, il va vous montrer la fonction exposée par la dll

dumpbin.exe /EXPORTS <PATH OF THE DLL>
1
répondu Ayush joshi 2018-03-18 06:33:19

j'ai cloné un outil très pratique, qui ajoute un menu contextuel pour les assemblages dans l'explorateur windows pour afficher toutes les informations disponibles:

télécharger ici: https://github.com/tebjan/AssemblyInformation/releases

enter image description here

1
répondu thalm 2018-08-18 18:06:49

voie plus générique - utiliser la structure du fichier pour déterminer le bitness et le type d'image:

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

mode de Compilation enumeration

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

code Source avec explication à GitHub

0
répondu BlackGad 2018-03-27 15:27:38