.net - voir - x86 x64 c'est quoi




Comment déterminer si un assembly.NET a été construit pour x86 ou x64? (9)

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

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

J'ai besoin de vérifier par programme si chaque DLL a été construite pour x86 (par opposition à x64 ou Any CPU). Est-ce possible?


Essayez d'utiliser CorFlagsReader de ce projet sur CodePlex . Il n'a aucune référence à d'autres assemblées et il peut être utilisé tel quel.


Méthode plus générique - utilisez la structure de fichier pour déterminer la quantité 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);
    }
}

Énumération du mode de compilation

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

Code source avec explication à GitHub


Que diriez-vous juste vous écrivez? Le noyau de l'architecture PE n'a pas été sérieusement modifié depuis son implémentation dans Windows 95. Voici un exemple 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;
    }
}

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


Une autre façon de vérifier la plate-forme cible d'un assembly .NET consiste à inspecter l'assembly avec .NET Reflector ...

@ # ~ # € ~! Je viens de réaliser que la nouvelle version n'est pas gratuite! Donc, la correction, si vous avez une version gratuite du réflecteur .NET, vous pouvez l'utiliser pour vérifier la plate-forme cible.


Une autre façon serait d'utiliser dumpbin à partir des outils Visual Studio sur DLL et 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: ci-dessus o / p est pour 32bit dll

Une option plus utile avec dumpbin.exe est / EXPORTS, il vous montrera la fonction exposée par la DLL

dumpbin.exe /EXPORTS <PATH OF THE DLL>

Vous trouverez ci-dessous un fichier batch qui exécutera corflags.exe rapport à toutes les dlls et exes du répertoire de travail courant et de tous les sous-répertoires, analysera les résultats et affichera l'architecture cible de chacun.

Selon la version de corflags.exe utilisée, les éléments de ligne dans la sortie incluront 32BITREQ ou 32BITREQ (et 32BITPREF ). Celui de ces deux éléments est inclus dans l'élément de campagne critique qui doit être vérifié pour différencier Any CPU et x86 . Si vous utilisez une ancienne version de corflags.exe (avant Windows SDK v8.0A), seul l'élément de corflags.exe sera présent dans la sortie, comme d'autres l'ont indiqué dans les réponses précédentes. Sinon 32BITREQ et 32BITPREF remplacent.

Cela suppose que corflags.exe trouve dans %PATH% . Le moyen le plus simple d'assurer cela consiste à utiliser une Developer Command Prompt . Vous pouvez également le copier depuis son emplacement par défaut .

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

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.

cfeduke note la possibilité d'appeler GetPEKind. Il est potentiellement intéressant de le faire avec PowerShell.

Voici, par exemple, le code d'une cmdlet pouvant être utilisée: https://.com/a/16181743/64257

Alternativement, à https://.com/a/4719567/64257 il est noté que "il ya aussi la cmdlet Get-PEHeader dans les extensions de communauté PowerShell qui peuvent être utilisées pour tester les images exécutables."


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






x86-64