.NET 어셈블리가 x86 또는 x64 용으로 구축되었는지 어떻게 알 수 있습니까?


327

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

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



2
당신은이 일을 확인 할 수 있습니다 : 체크하면-관리되지 않는-DLL은-IS-32 비트 또는 64 비트 .
Matt

2
.NET 4.5에 해당하는 이후 버전의 CorFlags에서 "32BIT"는 "32BITREQ"및 "32BITPREF"로 대체되었습니다. .
피터 Mortensen

답변:


280

보다 System.Reflection.AssemblyName.GetAssemblyName(string assemblyFile)

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

PowerShell 사용 :

[36] C : \> [reflection.assemblyname] :: GetAssemblyName ( "$ {pwd} \ Microsoft.GLEE.dll") | fl

이름 : Microsoft.GLEE
버전 : 1.0.0.0
CultureInfo :
코드베이스 : file : /// C : / projects / powershell / BuildAnalyzer / ...
EscapedCodeBase : 파일 : /// C : / projects / powershell / BuildAnalyzer / ...
프로세서 아키텍처 : MSIL
플래그 : PublicKey
해시 알고리즘 : SHA1
버전 호환성 : SameMachine
키 페어 :
성명 : Microsoft.GLEE, Version = 1.0.0.0, Culture = neut ... 

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

  • Amd64 : x64 아키텍처 기반의 64 비트 프로세서입니다.
  • Arm : ARM 프로세서
  • IA64 : 64 비트 Intel Itanium 프로세서 만 해당합니다.
  • MSIL : 프로세서 및 워드 당 비트 수와 관련하여 중립입니다.
  • X86 : 기본 또는 64 비트 플랫폼 (WOW64)의 Windows 기반 Windows 환경에있는 32 비트 Intel 프로세서.
  • None : 프로세서와 워드 당 비트의 알 수 없거나 지정되지 않은 조합입니다.

이 예제에서는 PowerShell을 사용하여 메서드를 호출하고 있습니다.


60
멍청한 질문을 용서하십시오-그러나 이것이 x86이라는 것을 알려줍니다.
George Mauer

53
ProcessorArchitecture 필드는 열거입니다. 위의 예에서는 "프로세서 및 워드 당 비트 수에 대해 중립적"인 MSIL로 설정되어 있습니다. 다른 값으로는 X86, IA64, Amd64가 있습니다. 자세한 내용은 msdn.microsoft.com/en-us/library/… 를 참조하십시오.
Brian Gillespie

4
함께 시도 [reflection.assemblyname]::GetAssemblyName("${pwd}\name.dll")때로는 프로세스의 현재 디렉토리가없는 것과 동일로 (필자는 DLL이 당신을 위해 가정입니다) 현재 제공자의
x0n가

2
인터넷에서 DLL을 다운로드 한 경우 DLL을 "차단 해제"하는 것을 잊어 버리는 또 다른주의 사항입니다. 차단 해제 파일을 사용하거나 탐색기에서 마우스 오른쪽 버튼을 클릭 / 속성 / 차단 해제하십시오. 가 차단 해제 상태를 인식하기 위해 이미 현재 세션에서 한 번 실패 한 경우 쉘을 다시 시작해야합니다 (즉에 대한 비난의 인터넷 익스플로러를 -. 정말 예)
x0n

1
ASP.NET MVC 코드에는 // DevDiv 216459: This code originally used Assembly.GetName(), but that requires FileIOPermission, which isn't granted in medium trust. However, Assembly.FullName *is* accessible in medium trust.슬프게도 GetName instance method; 를 사용하지 않고 ProcessorArchitecture를 읽을 수있는 방법이 없습니다 . 를 사용 AssemblyName constructor하면 필드가 항상로 설정됩니다 None.
metadings

221

당신은 사용할 수 있습니다 CorFlags CLI의 도구를 (예를 들어, C는 : \ 프로그램 파일 \은 Microsoft SDKs \ 윈도우 \ 7.0 \ 빈 \ CorFlags.exe가)의 상태를 결정하는 어셈블리, 그것의 출력과 같은 조립를 여는 기반 이진 자산 32BIT 플래그가 1 ( x86 ) 또는 0 ( 에 따라 임의의 CPU 또는 x64 )으로 설정되어 있는지 확인해야 할 위치를 결정할 수 있어야합니다 PE.

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

.NET사용한 x64 Development 블로그 게시물 에 대한 정보가 corflags있습니다.

더 좋은 방법 은 어셈블리가 다른 속성과 함께 값 (64 비트), (32 비트 및 WOW) 또는 (모든 CPU) 인지 확인하는 데 사용할Module.GetPEKind있습니다 .PortableExecutableKindsPE32PlusRequired32BitILOnly


1
업데이트를 본 후에 GetPEKind를 사용하는 것이 적절한 방법 인 것 같습니다. 나는 당신의 답변으로 표시했습니다.
유다 가브리엘 히 망고

9
32 비트 어셈블리를 검사 할 때 64 비트 프로세스에서 GetPEKind가 실패 함
jjxtra

2
32 비트 프로세스에서 GetPEKind를 호출해야합니다
Ludwo

2
VS 2008, VS 2010, VS 2012 및 VS 2013을 설치합니다. C : \ Program Files (x86) \ Microsoft SDKs \ Windows \의 하위 폴더에 8 개의 CorFlags.exe 파일이 있습니다. 어느 것을 사용해야합니까?
Kiquenet

5
이 답변 에서 지적했듯이 .NET 4.5에는 32BIT 플래그 대신 32BITREQ 및 32BITPREF가 있습니다. PE32 / 0 / 0 및 PE32 / 0 / 1은 각각 AnyCPU 및 AnyCPU 32 비트 선호입니다.
angularsen

141

명확히하기 위해 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

12
그동안 바뀌었던 것 같습니다. 지금 표시 corflags 32BITREQ32BITPREF보다는 하나의 32BIT값입니다.
OR Mapper

1
Microsoft .NET 4.5에는 새로운 옵션 인 모든 CPU 32 비트 기본 설정이 도입되었습니다. 자세한 내용은 다음과 같습니다 .
RBT

"Visual Studio 명령 프롬프트"는 현재 " Visual Studio 2019 개발자 명령 프롬프트 "라고합니다.
Uwe Keim

22

당신은 어떻게 당신이 자신을 작성? 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.

그러나이 방법을 사용하면 새로운 상수의 가능성을 허용하므로 적합하다고 판단 되는대로 수익을 검증하십시오.


1
흥미롭고 설명이있는 코드에 감사드립니다. Module.GetPEKind가 아마도 가장 쉬운 경로 일 것입니다. 그러나 이것은 학습을 위해 도움이됩니다. 감사.
유다 가브리엘 히 망고

3
매우 흥미롭지 만 Any CPU로 컴파일 된 응용 프로그램이 있으면 결과는 0x10B입니다. 내 응용 프로그램이 x64 시스템에서 실행되기 때문에 이것은 잘못된 것입니다. 확인할 다른 플래그가 있습니까?
사무엘

GetPEArchitecture는 .net 3.5, 4.0, 4.5 및 4.5.1을 사용하여 컴파일 된 어셈블리에서 작동합니까? 어쨌든 32 비트 어셈블리를 확인할 때 64 비트 프로세스에서 Module.GetPEKind가 실패한다고 생각합니다.
Kiquenet

9

CodePlex의이 프로젝트에서 CorFlagsReader 사용해보십시오 . 다른 어셈블리에 대한 참조가 없으며 그대로 사용할 수 있습니다.


1
이것이 가장 정확하고 유용한 답변입니다.
Kirill Osenkov

링크는이 글을 쓰는 시점에도 여전히 작동하지만 CodePlex가 곧 종료 될 예정이므로 너무 늦기 전에 적절한 조치를 취하는 것이 좋습니다.
피터 Mortensen


6
[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으로 빌드해야합니다. 단위 테스트를 추가하면 빌드 서버의 빌드 라이브러리가 32 비트가되고 이러한 실수가 발생하지 않도록합니다.)
Mido

5

아래는 corflags.exe모두에 대해 실행될 배치 파일입니다.dlls 그리고 exes현재 작업 디렉토리와 모든 하위 디렉토리에, 결과를 분석하고 각각의 목표 아키텍처를 표시합니다.

사용 된 버전에 따라 corflags.exe출력의 광고 항목에 32BIT, 또는 32BITREQ (및 32BITPREF)이 포함됩니다. 이 두 가지 중 어느 것이 출력에 포함되는지는 Any CPU과 를 구별하기 위해 확인해야하는 중요한 광고 항목입니다 x86. 이전 버전의 corflags.exe(Windows SDK v8.0A 이전)을 사용하는 경우 32BIT다른 사용자가 과거 답변에 표시 한대로 광고 항목 만 출력에 표시됩니다. 그렇지 않으면32BITREQ32BITPREF교체.

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

아래의 배치 파일이 관리되지 않는 dll또는 에 대해 실행 되면 실제 출력 결과 exe가로 잘못 표시 x86됩니다.Corflags.exe 은 다음과 유사한 오류 메시지가 됩니다.

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.

2

또 다른 방법은 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 OF THE DLL>

2

보다 일반적인 방법-파일 구조를 사용하여 비트 및 이미지 유형을 결정하십시오.

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

컴파일 모드 열거

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

GitHub 에서 설명하는 소스 코드



1

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

@ # ~ # € ~! 방금 새 버전이 공짜가 아니라는 것을 깨달았습니다! 따라서 수정 버전의 .NET 리플렉터가 있으면이를 사용하여 대상 플랫폼을 확인할 수 있습니다.


9
ILSpy를 사용하십시오. 이것은 리플렉터와 거의 동일한 기능을 수행하는 기본 오픈 소스 앱입니다.
Binary Worrier


1

이를위한 고급 애플리케이션 : 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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.