Question

J'ai une liste arbitraire d'assemblys .NET.

Je dois vérifier par programme si chaque DLL a été générée pour x86 (par opposition à x64 ou à tout processeur). Est-ce possible?

Était-ce utile?

La solution

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

Vous pouvez examiner les métadonnées d'assembly à partir de l'instance AssemblyName renvoyée:

Utilisation de 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.

  • Amd64 : processeur 64 bits basé sur l'architecture x64.
  • Armer : un processeur ARM.
  • IA64 : processeur Intel Itanium 64 bits uniquement.
  • MSIL : neutre par rapport au processeur et bits par mot.
  • X86 : Processeur Intel 32 bits, natif ou dans l'environnement Windows sur Windows sur une plate-forme 64 bits (WOW64).
  • Aucun : combinaison inconnue ou non précisée de processeur et de bits par mot.

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

Autres conseils

Vous pouvez utiliser le CorFlags outil CLI (par exemple, C: \ Program Files \ Microsoft SDK \ Windows \ v7 .0 \ Bin \ CorFlags.exe) pour déterminer l’état d’un assemblage, en fonction de sa sortie et de son ouverture en tant qu’actif binaire, vous devriez pouvoir déterminer où vous devez chercher si le drapeau 32BIT est défini sur 1 ( x86 ) ou 0 ( Tout processeur ou x64 , selon PE ):

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

L'article de blog Le développement x64 avec .NET contient des informations sur les annotations .

Encore mieux, vous pouvez utilisez Module.GetPEKind pour déterminer si un assembly est PortableExecutableKinds valeur PE32Plus (64 bits), Required32Bit (32 bits et WOW) ou ILOnly (tout processeur) avec d’autres attributs.

Juste pour clarifier, CorFlags.exe fait partie du SDK .NET Framework . J'ai les outils de développement sur ma machine et le moyen le plus simple de déterminer si une DLL est uniquement en 32 bits consiste à:

  1. Ouvrez l'invite de commandes Visual Studio (Dans Windows: menu Démarrer / Programmes / Microsoft Visual Studio / Outils de Visual Studio / Invite de commandes Visual Studio 2008)

  2. CD dans le répertoire contenant la DLL en question

  3. Exécutez les corflags comme ceci: corflags MyAssembly.dll

Vous obtiendrez quelque chose comme ceci:

    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 indicateurs ci-dessus doivent être lus comme suit:

  • Tout processeur: PE = PE32 et 32BIT = 0
  • x86: PE = PE32 et 32BIT = 1
  • 64 bits: PE = PE32 + et 32BIT = 0

Et si vous écriviez vous-même? Le cœur de l’architecture PE n’a pas été sérieusement modifié depuis son implémentation dans Windows 95. Voici un exemple en 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;
    }
}

Les constantes actuelles sont les suivantes:

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 bon vous semble.

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

Ci-dessous, un fichier de commandes qui exécutera corflags.exe sur tous les dlls et exes du répertoire de travail en cours et de tous les sous-répertoires. , analyser les résultats et afficher l’architecture cible de chacun.

En fonction de la version de corflags.exe utilisée, les éléments de ligne de la sortie incluent 32BIT , ou 32BITREQ (et 32BITPREF ). L'élément de la ligne critique devant être vérifié pour différencier Tout CPU et x86 est celui qui est inclus dans la sortie. Si vous utilisez une version antérieure de corflags.exe (version antérieure à Windows SDK v8.0A), seul l'élément de ligne 32BIT sera présent dans le résultat, comme d'autres l'ont déjà fait. indiqué dans les réponses précédentes. Sinon, 32BITREQ et 32BITPREF le remplacent.

Cela suppose que corflags.exe se trouve dans le % PATH% . Pour ce faire, le moyen le plus simple consiste à utiliser une invite de commande du développeur . Vous pouvez également le copier à partir de son emplacement par défaut .

Si le fichier de commandes ci-dessous est exécuté sur une dll ou exe non géré, il sera affiché incorrectement sous le nom x86 , car la sortie réelle à partir de Corflags.exe sera un message d'erreur semblable à:

  

corflags: erreur 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.

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

Une autre solution consiste à utiliser dumpbin à partir des outils Visual Studio sur une DLL et à rechercher 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

Remarque: ci-dessus, o / p correspond à une dll 32 bits

Une autre option utile avec dumpbin.exe est / EXPORTS, elle vous montrera la fonction exposée par la dll

dumpbin.exe /EXPORTS <PATH OF THE DLL>

J'ai cloné un outil extrêmement pratique qui ajoute une entrée de menu contextuel pour les assemblages dans l'explorateur Windows afin d'afficher toutes les informations disponibles:

Téléchargez ici: https://github.com/tebjan/AssemblyInformation/releases

 entrer la description de l'image ici

Une application plus avancée pour cela 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

Manière plus générique - utilisez la structure de fichier pour déterminer le nombre de bits et le type d'image:

public static CompilationMode GetCompilationMode(this FileInfo info)
{
    if (!info.Exists) throw new ArgumentException(
[Flags]
public enum CompilationMode
{
    Invalid = 0,
    Native = 0x1,
    CLR = Native << 1,
    Bit32 = CLR << 1,
    Bit64 = Bit32 << 1
}
quot;{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); } }

Énumération en mode compilation

<*>

Code source avec explication à l'adresse GitHub

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top