How can I determine if a .NET assembly was built for x86 or x64?

后端 未结 15 878
面向向阳花
面向向阳花 2020-11-22 09:08

I\'ve got an arbitrary list of .NET assemblies.

I need to programmatically check if each DLL was built for x86 (as opposed to x64 or Any CPU). Is this possible?

相关标签:
15条回答
  • 2020-11-22 09:23

    DotPeek from JetBrains provides quick and easy way to see msil(anycpu), x86, x64

    0 讨论(0)
  • 2020-11-22 09:25

    Below is a batch file that will run corflags.exe against all dlls and exes in the current working directory and all sub-directories, parse the results and display the target architecture of each.

    Depending on the version of corflags.exe that is used, the line items in the output will either include 32BIT, or 32BITREQ (and 32BITPREF). Whichever of these two is included in the output is the critical line item that must be checked to differentiate between Any CPU and x86. If you are using an older version of corflags.exe (pre Windows SDK v8.0A), then only the 32BIT line item will be present in the output, as others have indicated in past answers. Otherwise 32BITREQ and 32BITPREF replace it.

    This assumes corflags.exe is in the %PATH%. The simplest way to ensure this is to use a Developer Command Prompt. Alternatively you could copy it from it's default location.

    If the batch file below is run against an unmanaged dll or exe, it will incorrectly display it as x86, since the actual output from Corflags.exe will be an error message similar to:

    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.
    
    0 讨论(0)
  • 2020-11-22 09:26

    How about you just write you own? The core of the PE architecture hasn't been seriously changed since its implementation in Windows 95. Here's a C# example:

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

    Now the current constants are:

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

    But with this method it allows for the possibilities of new constants, just validate the return as you see fit.

    0 讨论(0)
  • 2020-11-22 09:27

    Try to use CorFlagsReader from this project at CodePlex. It has no references to other assemblies and it can be used as is.

    0 讨论(0)
  • 2020-11-22 09:29

    Just for clarification, CorFlags.exe is part of the .NET Framework SDK. I have the development tools on my machine, and the simplest way for me determine whether a DLL is 32-bit only is to:

    1. Open the Visual Studio Command Prompt (In Windows: menu Start/Programs/Microsoft Visual Studio/Visual Studio Tools/Visual Studio 2008 Command Prompt)

    2. CD to the directory containing the DLL in question

    3. Run corflags like this: corflags MyAssembly.dll

    You will get output something like this:

    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
    

    As per comments the flags above are to be read as following:

    • Any CPU: PE = PE32 and 32BIT = 0
    • x86: PE = PE32 and 32BIT = 1
    • 64-bit: PE = PE32+ and 32BIT = 0
    0 讨论(0)
  • 2020-11-22 09:36

    Look at System.Reflection.AssemblyName.GetAssemblyName(string assemblyFile)

    You can examine assembly metadata from the returned AssemblyName instance:

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

    Here, ProcessorArchitecture identifies target platform.

    • Amd64: A 64-bit processor based on the x64 architecture.
    • Arm: An ARM processor.
    • IA64: A 64-bit Intel Itanium processor only.
    • MSIL: Neutral with respect to processor and bits-per-word.
    • X86: A 32-bit Intel processor, either native or in the Windows on Windows environment on a 64-bit platform (WOW64).
    • None: An unknown or unspecified combination of processor and bits-per-word.

    I'm using PowerShell in this example to call the method.

    0 讨论(0)
提交回复
热议问题