ฉันจะทราบได้อย่างไรว่าแอสเซมบลี. NET นั้นถูกสร้างขึ้นสำหรับ x86 หรือ x64 หรือไม่


327

ฉันมีรายชื่อชุดประกอบ. NET

ฉันต้องตรวจสอบโดยทางโปรแกรมว่า DLL แต่ละตัวถูกสร้างขึ้นสำหรับ x86 (ตรงข้ามกับ x64 หรือ CPU ใด ๆ ) เป็นไปได้ไหม



2
นอกจากนี้คุณยังอาจต้องการที่จะตรวจสอบหนึ่งนี้: เช็คถ้าไม่มีการจัดการ--dll-is-32 บิตหรือ 64 บิต
Matt

2
ใน CorFlags รุ่นที่ใหม่กว่าซึ่งสอดคล้องกับ. NET 4.5, "32BIT" ถูกแทนที่ด้วย "32BITREQ" และ "32BITPREF" .
ปีเตอร์มอร์เทนเซ่น

คำตอบ:


280

ดูที่ System.Reflection.AssemblyName.GetAssemblyName(string assemblyFile)

คุณสามารถตรวจสอบข้อมูลเมตาของแอสเซมบลีจากอินสแตนซ์ AssemblyName ที่ส่งคืน:

ใช้PowerShell :

[36] C: \> [reflection.assemblyname] :: GetAssemblyName ("$ {pwd} \ Microsoft.GLEE.dll") | ฟลอริด้า

ชื่อ: Microsoft.GLEE
เวอร์ชัน: 1.0.0.0
CultureInfo:
CodeBase: ไฟล์: /// C: / โครงการ / powershell / BuildAnalyzer / ...
EscapedCodeBase: ไฟล์: /// C: / projects / powershell / BuildAnalyzer / ...
สถาปัตยกรรมโปรเซสเซอร์: MSIL
ธง: PublicKey
HashAlgorithm: SHA1
VersionCompatibility: SameMachine
KeyPair:
FullName: Microsoft.GLEE, เวอร์ชัน = 1.0.0.0, Culture = neut ... 

ที่นี่ProcessorArchitectureระบุแพลตฟอร์มเป้าหมาย

  • Amd64 : ตัวประมวลผล 64 บิตที่ใช้สถาปัตยกรรม x64
  • แขน : หน่วยประมวลผล ARM
  • IA64 : โปรเซสเซอร์ Intel Itanium 64 บิตเท่านั้น
  • MSIL : เป็นกลางเกี่ยวกับโปรเซสเซอร์และบิตต่อคำ
  • X86 : ตัวประมวลผล Intel 32 บิตไม่ว่าจะเป็นแบบดั้งเดิมหรือใน Windows บนระบบ Windows บนแพลตฟอร์ม 64 บิต (WOW64)
  • ไม่มี : การรวมกันที่ไม่รู้จักหรือไม่ระบุของตัวประมวลผลและบิตต่อคำ

ฉันใช้ PowerShell ในตัวอย่างนี้เพื่อเรียกวิธีการ


60
ยกโทษให้กับคำถามโง่ ๆ - แต่ในกรณีนี้จะบอกอะไรคุณว่า x86
George Mauer

53
ฟิลด์ ProcessorAr Architecture คือการแจงนับ ในตัวอย่างด้านบนตั้งเป็น MSIL ซึ่งหมายถึง "เป็นกลางเกี่ยวกับโปรเซสเซอร์และบิตต่อคำ" ค่าอื่น ๆ ได้แก่ X86, IA64, Amd64 ดูmsdn.microsoft.com/en-us/library/…สำหรับรายละเอียดเพิ่มเติม
Brian Gillespie

4
ลอง[reflection.assemblyname]::GetAssemblyName("${pwd}\name.dll")เป็นบางครั้งไดเรกทอรีปัจจุบันของกระบวนการไม่เหมือนกับผู้ให้บริการปัจจุบัน (ซึ่งเป็นที่ที่ฉันถือว่า DLL สำหรับคุณ)
x0n

2
ข้อแม้อื่นที่ต้องระวังคือลืม "เลิกบล็อก" DLL หากคุณดาวน์โหลดจาก internets ใช้ unblock-file หรือคลิกขวา / properties / unblock จาก explorer คุณจะต้องรีสตาร์ทเชลล์เพื่อให้ทราบสถานะที่ไม่ถูกบล็อกหากคุณล้มเหลวครั้งหนึ่งในเซสชั่นปัจจุบัน (ตำหนิ Internet explorer - ใช่ใช่จริงๆ)
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.น่าเศร้าที่ไม่มีวิธีการอ่าน ProcessorAr Architecture โดยไม่ต้องใช้GetName instance method; โดยใช้ข้อมูลที่มีการตั้งเสมอAssemblyName constructor None
metadings

221

คุณสามารถใช้เครื่องมือCorFlags CLI (ตัวอย่าง SDKs \ Windows \ v7.0 \ BinFlags.exe Files \ Microsoft C: \ Program) เพื่อตรวจสอบสถานะของแอสเซมบลีตามเอาท์พุทและเปิดแอสเซมบลีเป็น สินทรัพย์ไบนารีคุณควรจะสามารถระบุตำแหน่งที่คุณต้องการค้นหาเพื่อตรวจสอบว่าการตั้งค่าสถานะ 32BIT เป็น 1 ( x86 ) หรือ 0 ( CPUหรือx64 ใด ๆขึ้นอยู่กับPE):

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

บล็อกโพสต์การพัฒนา x64 กับ .NETcorflagsมีข้อมูลบางอย่างเกี่ยวกับ

ยิ่งไปกว่านั้นคุณสามารถใช้Module.GetPEKindเพื่อกำหนดว่าแอสเซมบลีเป็นPortableExecutableKindsค่าPE32Plus(64 บิต), Required32Bit(32- บิตและ WOW) หรือILOnly(CPU ใด ๆ ) พร้อมกับคุณลักษณะอื่น ๆ


1
หลังจากเห็นการอัปเดตของคุณการใช้ GetPEKind น่าจะเป็นวิธีที่เหมาะสมในการทำสิ่งนี้ ฉันทำเครื่องหมายว่าคุณเป็นคำตอบ
Judah Gabriel Himango

9
GetPEKind ล้มเหลวในกระบวนการ 64 บิตเมื่อตรวจสอบชุดประกอบ 32 บิต
jjxtra

2
คุณต้องโทร GetPEKind จากกระบวนการ 32 บิต
Ludwo

2
ฉันติดตั้ง VS 2008, VS 2010, VS 2012 และ VS 2013 ฉันมี 8 ไฟล์ CorFlags.exe ในโฟลเดอร์ย่อยใน C: \ Program Files (x86) \ Microsoft SDKs \ Windows \ ควรใช้แบบไหน
Kiquenet

5
ตามที่ระบุไว้ในคำตอบนี้ใน. NET 4.5 มี 32BITREQ และ 32BITPREF แทนการตั้งค่าสถานะ 32BIT PE32 / 0/0 และ PE32 / 0/1 เป็นที่ต้องการ AnyCPU และ AnyCPU 32- บิตตามลำดับ
angularsen

141

เพียงเพื่อชี้แจง CorFlags.exe เป็นส่วนหนึ่งของ.NET Framework SDK ฉันมีเครื่องมือในการพัฒนาบนเครื่องของฉันและวิธีที่ง่ายที่สุดสำหรับฉันกำหนดว่า DLL เป็น 32 บิตเท่านั้น:

  1. เปิดพรอมต์คำสั่ง Visual Studio (ใน Windows: เมนู Start / Programs / Microsoft Visual Studio / Visual Studio Tools / พรอมต์คำสั่ง Visual Studio 2008)

  2. CD ไปยังไดเรกทอรีที่มี DLL ที่เป็นปัญหา

  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 จะแสดง32BITREQและ32BITPREFมากกว่า32BITค่าเดียว
หรือผู้ทำแผนที่

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 น่าจะเป็นเส้นทางที่ง่ายที่สุด แต่สิ่งนี้มีประโยชน์สำหรับการเรียนรู้ ขอบคุณ
ยูดาห์กาเบรียล Himango

3
น่าสนใจมาก แต่เมื่อฉันมีแอปพลิเคชันที่คอมไพล์ด้วย CPU ใด ๆ ผลที่ได้คือ 0x10B สิ่งนี้ผิดเพราะแอปพลิเคชันของฉันทำงานในระบบ x64 มีธงอื่น ๆ เพื่อตรวจสอบหรือไม่
ซามูเอล

GetPEAr Architecture ทำงานสำหรับแอสเซมบลีที่คอมไพล์โดยใช้. net 3.5, 4.0, 4.5 และ 4.5.1 อย่างไรก็ตามฉันคิดว่า Module.GetPEKind ล้มเหลวในกระบวนการ 64 บิตเมื่อตรวจสอบชุดประกอบ 32 บิต
Kiquenet

9

พยายามที่จะใช้ CorFlagsReader จากโครงการนี้ที่ CodePlex มันไม่มีการอ้างอิงถึงแอสเซมบลีอื่นและสามารถใช้ตามที่เป็นอยู่


1
นี่คือคำตอบที่ถูกต้องและมีประโยชน์ที่สุด
คิริลล์โอเซนคอฟ

ลิงก์ยังคงใช้งานได้เหมือนการเขียนนี้ แต่เนื่องจาก CodePlex กำลังจะปิดตัวลงจึงเป็นการดีที่จะดำเนินการตามความเหมาะสมก่อนที่จะสายเกินไป
ปีเตอร์มอร์เทนเซ่น


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 เพิ่มการทดสอบหน่วยเพื่อให้แน่ใจว่า
Mido

5

ด้านล่างนี้เป็นไฟล์แบตช์ที่จะทำงานcorflags.exeกับทั้งหมดdllsและexesในไดเรกทอรีการทำงานปัจจุบันและไดเรกทอรีย่อยทั้งหมดแยกวิเคราะห์ผลลัพธ์และแสดงสถาปัตยกรรมเป้าหมายของแต่ละรายการ

ทั้งนี้ขึ้นอยู่กับรุ่นของcorflags.exeที่ใช้ในรายการโฆษณาในการส่งออกทั้งสองจะรวมถึง32BIT, หรือ 32BITREQ (และ32BITPREF) แล้วแต่จำนวนใดของทั้งสองจะรวมอยู่ในการส่งออกเป็นบรรทัดรายการที่สำคัญที่จะต้องตรวจสอบความแตกต่างระหว่างและAny CPU x86หากคุณใช้เวอร์ชันเก่ากว่าcorflags.exe(pre pre SDK ของ Windows SDK v8.0A) เฉพาะ32BITรายการโฆษณาเท่านั้นที่จะปรากฏในผลลัพธ์ตามที่คนอื่น ๆ ระบุไว้ในคำตอบที่ผ่านมา มิฉะนั้น32BITREQและ32BITPREFแทนที่

นี้จะถือว่าอยู่ใน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

อีกวิธีหนึ่งคือการใช้ dumpbin จากเครื่องมือ Visual Studio บน DLL และค้นหาผลลัพธ์ที่เหมาะสม

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

หมายเหตุ: Above 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


2

ฉันโคลนเครื่องมือที่มีประโยชน์อย่างยิ่งที่เพิ่มรายการเมนูบริบทสำหรับชุดประกอบใน windows explorer เพื่อแสดงข้อมูลที่มีอยู่ทั้งหมด:

ดาวน์โหลดได้ที่นี่: https://github.com/tebjan/AssemblyInformation/releases

ป้อนคำอธิบายรูปภาพที่นี่


1

อีกวิธีในการตรวจสอบแพลตฟอร์มเป้าหมายของชุดประกอบ. NET คือการตรวจสอบชุดประกอบด้วย. NET Reflector ...

@ # ~ # € ~! ฉันเพิ่งรู้ว่าเวอร์ชันใหม่ไม่ฟรี! ดังนั้นการแก้ไขถ้าคุณมี. NET รุ่นสะท้อนแสงฟรีคุณสามารถใช้มันเพื่อตรวจสอบแพลตฟอร์มเป้าหมาย


9
ใช้ILSpyเป็นแอพโอเพนซอร์ซพื้นฐานที่ทำสิ่งเดียวกับ Reflector
Binary Worrier

1

cfeduke บันทึกความเป็นไปได้ของการโทร GetPEKind เป็นเรื่องที่น่าสนใจที่จะทำสิ่งนี้จาก PowerShell

ตัวอย่างเช่นที่นี่คือรหัสสำหรับ cmdlet ที่สามารถใช้ได้: https://stackoverflow.com/a/16181743/64257

อีกวิธีหนึ่งที่https://stackoverflow.com/a/4719567/64257มีการบันทึกไว้ว่า "นอกจากนี้ยังมี Get-PEHeader cmdlet ในPowerShell Community Extensionsที่สามารถใช้ในการทดสอบภาพที่ปฏิบัติการได้"


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.