.NET 어셈블리가 x86 또는 x64 용으로 빌드되었는지 확인하는 방법


.NET 어셈블리의 임의 목록이 있습니다.

각 DLL이 x64 또는 모든 CPU와는 반대로 x86 용으로 빌드되었는지 프로그래밍 방식으로 확인해야합니다. 이것이 가능한가?



Answers



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

반환 된 AssemblyName 인스턴스에서 어셈블리 메타 데이터를 검사 할 수 있습니다.

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

여기서 ProcessorArchitecture 는 대상 플랫폼을 식별합니다.

이 예제에서 PowerShell을 사용하여 메서드를 호출합니다.




CorFlags CLI 도구 (예 : C : \ Program Files \ Microsoft SDKs \ Windows \ v7.0 \ Bin \ CorFlags.exe)를 사용하여 어셈블리의 출력을 기준으로 어셈블리의 상태를 확인하고 어셈블리를 바이너리 자산을 사용하려면 32BIT 플래그가 1 ( x86 ) 또는 0 ( PE 에 따라 모든 CPU 또는 x64 )으로 설정되어 있는지 확인해야 할 위치를 결정할 수 있어야합니다.

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

블로그 게시물 x64 .NET 개발 에는 corflags 에 대한 정보가 있습니다.

더 좋게는 Module.GetPEKind사용 하여 다른 속성과 함께 PortableExecutableKindsPE32Plus (64 비트), Required32Bit (32 비트 및 WOW) 또는 ILOnly (모든 CPU)인지 여부를 확인할 수 있습니다 .




명확히하기 위해 CorFlags.exe는 .NET Framework SDK의 일부입니다. 내 컴퓨터에 개발 도구가 있는데 가장 간단한 방법은 DLL이 32 비트인지 여부를 결정하는 것입니다.

  1. Visual Studio 명령 프롬프트를 엽니 다 (Windows의 경우 : 시작 / 프로그램 / Microsoft Visual Studio / Visual Studio 도구 / Visual Studio 2008 명령 프롬프트)

  2. 해당 DLL이 들어있는 디렉토리에 CD를 넣으십시오.

  3. corflags를 다음과 같이 실행합니다. corflags MyAssembly.dll

다음과 같은 결과가 나옵니다.

    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

의견에 따라 위의 플래그는 다음과 같이 읽어야합니다.

  • 모든 CPU : PE = PE32 및 32BIT = 0
  • x86 : PE = PE32 및 32BIT = 1
  • 64 비트 : PE = PE32 + 및 32BIT = 0



그냥 자기 자신을 쓰는 건 어때? PE 아키텍처의 핵심은 Windows 95에서 구현 된 이후로 심각하게 변경되지 않았습니다. 다음은 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;
    }
}

이제 현재 상수는 다음과 같습니다.

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

그러나이 방법을 사용하면 새로운 상수의 가능성을 고려할 수 있습니다.







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



아래는 현재 작업 디렉토리 및 모든 하위 디렉토리의 모든 dllsexes 에 대해 corflags.exe 를 실행하고 결과를 파싱하고 각각의 대상 아키텍처를 표시하는 배치 파일입니다.

사용되는 corflags.exe 의 버전에 따라 출력의 행 항목에는 32BITREQ 또는 32BITREQ (및 32BITPREF )가 포함됩니다. 이 두 가지 중 출력에 포함되는 것은 Any CPUx86 을 구별하기 위해 검사해야하는 중요한 항목입니다. 이전 버전의 corflags.exe (Windows SDK v8.0A 이전 버전)를 사용하는 경우 다른 사람이 이전 답변에서 지정한대로 32BIT 항목 만 출력에 나타납니다. 그렇지 않으면 32BITREQ32BITPREF 32BITREQ32BITPREF .

이것은 corflags.exe%PATH% 에 있다고 가정합니다. 이를 보장하는 가장 간단한 방법은 Developer Command Prompt 를 사용하는 것입니다. 또는 기본 위치 에서 복사 할 수 있습니다 .

아래의 배치 파일을 관리되지 않는 dll 또는 exe 에 대해 실행하면 Corflags.exe 의 실제 출력은 Corflags.exe 과 비슷한 오류 메시지가되므로 x86 으로 잘못 표시됩니다.

corflags : 오류 CF008 : 지정된 파일에 유효한 관리되는 헤더가 없습니다.

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



.NET 어셈블리의 대상 플랫폼을 확인하는 또 다른 방법은 .NET Reflector를 사용 하여 어셈블리를 검사하는 것입니다.

@ # ~ # € ~! 나는 새로운 버전이 무료가 아니라는 것을 깨달았습니다! 따라서 .NET Reflector의 무료 버전을 사용하는 경우이를 수정하여 대상 플랫폼을 확인할 수 있습니다.




cfeduke는 GetPEKind를 호출 할 가능성을 설명합니다. PowerShell에서이 작업을 수행하는 것이 잠재적으로 흥미 롭습니다.

예를 들어, 사용할 수있는 cmdlet 코드는 다음과 같습니다. https://.com/a/16181743/64257

또는 https://.com/a/4719567/64257 에서 "실행 가능 이미지를 테스트하는 데 사용할 수있는 PowerShell 커뮤니티 확장 에 Get-PEHeader cmdlet도 있습니다."




더 고급 응용 프로그램을 찾으려면 여기를 참조하십시오. CodePlex - ApiChange

예 :

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



한 가지 더 많은 방법은 DLL의 Visual Studio 도구에서 dumpbin을 사용하여 적절한 출력을 찾는 것입니다

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

참고 : 위의 o / p는 32 비트 dll입니다.

dumpbin.exe의 유용한 옵션은 / EXPORTS입니다. dll에 의해 노출 된 함수를 보여줍니다

dumpbin.exe /EXPORTS <PATH OD THE DLL>



JetBrians의 DotPeek은 msil (anycpu), x86, x64를 빠르고 쉽게 볼 수있는 방법을 제공합니다