अगर कोई .NET असेंबली x86 या x64 के लिए बनाया गया था, तो मैं कैसे निर्धारित कर सकता हूं?


327

मुझे .NET असेंबली की एक मनमानी सूची मिली है।

यदि प्रत्येक DLL x86 (x64 या किसी भी CPU के विपरीत) के लिए बनाया गया था, तो मुझे प्रोग्रामेटिक रूप से जांचने की आवश्यकता है। क्या यह संभव है?




2
.NET 4.5 के बाद के कॉर्फ़्लैग्स के बाद के संस्करण में, "32BIT" को "32BITREQ" और "32BITPREF" द्वारा बदल दिया गया था।
पीटर मोर्टेंसन

जवाबों:


280

की ओर देखें System.Reflection.AssemblyName.GetAssemblyName(string assemblyFile)

आप असेंबली मेटाडेटा को दिए गए असेंबली उदाहरण से जाँच सकते हैं:

PowerShell का उपयोग करना :

[३६] C: \> [प्रतिबिंब.assemblyname] :: GetAssemblyName ("$ {pwd} \ Microsoft.GLEE.dll") | fl

नाम: Microsoft.GLEE
संस्करण: 1.0.0.0
संस्कृतिइन्फो:
CodeBase: फ़ाइल: /// C: / प्रोजेक्ट्स / शक्तियाँ / BuildAnalyzer / ...
EscapedCodeBase: फ़ाइल: /// C: / प्रोजेक्ट्स / शक्तियाँ / BuildAnalyzer / ...
प्रोसेसरऑर्किटेक्चर: एम.एस.आई.एल.
झंडे: PublicKey
हशालिअल्मोगम: SHA1
संस्करणकंपनीयता: समानचिन
कीपेयर:
FullName: Microsoft.GLEE, संस्करण = 1.0.0.0, संस्कृति = न्युट ... 

यहाँ, ProcessorArchitecture लक्ष्य प्लेटफ़ॉर्म की पहचान करता है।

  • Amd64 : x64 आर्किटेक्चर पर आधारित 64-बिट प्रोसेसर।
  • शाखा : एक एआरएम प्रोसेसर।
  • IA64 : केवल 64-बिट इंटेल इटेनियम प्रोसेसर।
  • MSIL : प्रोसेसर और बिट्स-प्रति-शब्द के संबंध में तटस्थ।
  • X86 : एक 32-बिट इंटेल प्रोसेसर, देशी या विंडोज में 64-बिट प्लेटफॉर्म (WOW64) पर विंडोज वातावरण पर।
  • कोई नहीं : प्रोसेसर और बिट्स-प्रति-शब्द का एक अज्ञात या अनिर्दिष्ट संयोजन।

मैं इस उदाहरण में PowerShell का उपयोग विधि को कॉल करने के लिए कर रहा हूं।


60
मूर्खतापूर्ण प्रश्न को क्षमा करें - लेकिन इसमें आपको क्या कहना है कि यह x86 है?
जॉर्ज मौअर

53
ProcessorArchitecture फ़ील्ड एक एन्यूमरेशन है; उपरोक्त उदाहरण में यह MSIL के लिए सेट है, जिसका अर्थ है "प्रोसेसर और बिट्स-प्रति शब्द के संबंध में तटस्थ।" अन्य मूल्यों में X86, IA64, Amd64 शामिल हैं। अधिक जानकारी के लिए msdn.microsoft.com/en-us/library/… देखें ।
ब्रायन गिलेस्पी

4
[reflection.assemblyname]::GetAssemblyName("${pwd}\name.dll")कभी-कभी प्रक्रिया के साथ प्रयास करें कि वर्तमान निर्देशिका वर्तमान प्रदाता के समान नहीं है (जो कि मुझे लगता है कि DLL आपके लिए है)
x0n

2
अगर आप इसे इंटर्नेट से डाउनलोड करते हैं तो डीएलएल "अनब्लॉक" करना भूल जाता है। अनब्लॉक-फाइल का उपयोग करें, या एक्सप्लोरर से राइट क्लिक / प्रॉपर्टीज / अनब्लॉक करें। यदि आपने वर्तमान सत्र (उस के लिए इंटरनेट एक्सप्लोरर को दोष दिया है - हाँ, वास्तव में।)
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.कि अफसोस की बात है, वहाँ का उपयोग करने के बिना ProcessorArchitecture पढ़ने का कोई तरीका नहीं है GetName instance method; का उपयोग करते हुए AssemblyName constructor, क्षेत्र हमेशा के लिए सेट है None
मेटाडिंग्स

221

आप किसी असेंबली की स्थिति, उसके आउटपुट के आधार पर और असेंबली खोलने के रूप में निर्धारित करने के लिए CorFlags CLI टूल (उदाहरण के लिए, C: \ Program Files \ Microsoft SDKs \ Windows \ v7.0 \ Bin \ CorFlags.exe) का उपयोग कर सकते हैं बाइनरी एसेट आपको यह निर्धारित करने में सक्षम होना चाहिए कि आपको यह निर्धारित करने की आवश्यकता है कि क्या 32BIT ध्वज 1 ( x86 ) या 0 ( किसी भी CPU या x64 पर निर्भर करता है PE) पर सेट है:

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

.NET के साथ ब्लॉग पोस्ट x64 डेवलपमेंट के बारे में कुछ जानकारी हैcorflags

इससे भी बेहतर, आप यह निर्धारित करने के लिए उपयोगModule.GetPEKind कर सकते हैं कि क्या एक विधानसभा PortableExecutableKindsमूल्य PE32Plus(64-बिट), Required32Bit(32-बिट और वाह), या ILOnlyअन्य विशेषताओं के साथ (किसी भी सीपीयू) है।


1
आपके अपडेट को देखने के बाद, GetPEKind का उपयोग करना ऐसा करने का उचित तरीका लगता है। मैंने तुम्हारा जवाब के रूप में चिह्नित किया है।
जुडाह गेब्रियल हिमंगो

9
GetPEKind 64 बिट प्रक्रिया में विफल रहता है जब 32 बिट असेंबलियों की जाँच करते हैं
jjxtra

2
आपको GetbitKind को 32bit प्रक्रिया से कॉल करना है
लुडोवो

2
मैं VS 2008, VS 2010, VS 2012 और VS 2013 स्थापित करता हूं। मेरे पास C: \ Program Files (x86) \ Microsoft SDKs \ Windows \ में सबफ़ोल्डर में 8 फाइलें CorFlags.exe हैं। जो मुझे उपयोग करना चाहिए?
कीकेनेट

5
जैसा कि इस उत्तर में कहा गया है , .NET 4.5 में 32BITREQ और 32BITPREF की जगह 32BIT ध्वज है। PE32 / 0/0 और PE32 / 0/1 AnyCPU और AnyCPU क्रमशः 32-बिट पसंदीदा हैं।
कोणीयलेन

141

स्पष्टीकरण के लिए, CorFlags.exe .NET फ्रेमवर्क एसडीके का हिस्सा है । मेरे पास मेरी मशीन पर विकास उपकरण हैं, और मेरे लिए सबसे सरल तरीका यह निर्धारित करता है कि क्या DLL 32-बिट केवल है:

  1. Visual Studio कमांड प्रॉम्प्ट खोलें (Windows में: मेनू प्रारंभ / कार्यक्रम / Microsoft Visual Studio / विज़ुअल स्टूडियो टूल / विज़ुअल स्टूडियो 2008 कमांड प्रॉम्प्ट)

  2. प्रश्न में 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-बिट पसंदीदा। यहाँ विवरण हैं।
आरबीटी

"विज़ुअल स्टूडियो कमांड प्रॉम्प्ट" को आजकल " विज़ुअल स्टूडियो 2019 डेवलपर कमांड प्रॉम्प्ट " कहा जाता है।
उवे कीम

22

कैसे के बारे में तुम सिर्फ तुम ही लिख? Windows 95 में इसके लागू होने के बाद से PE आर्किटेक्चर के कोर को गंभीरता से नहीं बदला गया है। यहाँ एक 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
दिलचस्प है, स्पष्टीकरण के साथ कोड के लिए धन्यवाद। मॉड्यूल। GetPEKind शायद सबसे आसान रास्ता है। लेकिन यह सीखने के लिए मददगार है। धन्यवाद।
यहूदा गैब्रियल हिमंगो

3
बहुत दिलचस्प है, लेकिन जब मेरे पास किसी भी सीपीयू के साथ एक आवेदन संकलित होता है, तो परिणाम 0x10B होता है। यह गलत है क्योंकि मेरा आवेदन एक x64 सिस्टम में चलाया गया है। क्या जाँच करने के लिए कोई और झंडा है?
शमूएल

GetPEArchitecture .net 3.5, 4.0, 4.5 और 4.5.1 का उपयोग करके संकलित असेंबली के लिए काम करता है? वैसे भी, मुझे लगता है, 32 बिट असेंबलियों की जाँच करते समय Module.GetPEKind 64 बिट प्रक्रिया में विफल रहता है।
किकेनेट

9

CodePlex में इस परियोजना से CorFlagsReader का उपयोग करने का प्रयास करें । इसका अन्य विधानसभाओं के लिए कोई संदर्भ नहीं है और इसका उपयोग किया जा सकता है।


1
यह सबसे सटीक और उपयोगी उत्तर है।
किरिल ओसेनकोव

लिंक अभी भी इस लेखन के रूप में काम करता है, लेकिन जैसा कि कोडप्लेक्स बंद होने वाला है, बहुत देर होने से पहले उचित कार्रवाई करना अच्छा होगा।
पीटर मोर्टेंसन


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(पूर्व विंडोज एसडीके 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

एक और तरीका यह होगा कि 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

नोट: ऊपर o / p 32 बिट dll के लिए है

डंपबिन। Ex के साथ एक और उपयोगी विकल्प / एक्सपोर्ट है, यह आपको 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

मैंने एक सुपर आसान टूल क्लोन किया है जो सभी उपलब्ध जानकारी को दिखाने के लिए विंडोज़ एक्सप्लोरर में असेंबली के लिए एक संदर्भ मेनू प्रविष्टि जोड़ता है:

यहाँ डाउनलोड करें: https://github.com/tebjan/AssemblyInformation/releases

यहां छवि विवरण दर्ज करें


1

.NET असेंबली के टारगेट प्लेटफ़ॉर्म की जाँच करने का एक और तरीका .NET रिफ्लेक्टर के साथ असेंबली का निरीक्षण कर रहा है ...

@ # ~ # € ~! मैंने अभी महसूस किया है कि नया संस्करण मुफ्त नहीं है! इसलिए, सुधार, यदि आपके पास .NET रिफ्लेक्टर का मुफ्त संस्करण है, तो आप इसका उपयोग लक्ष्य प्लेटफ़ॉर्म की जांच करने के लिए कर सकते हैं।


9
ILSpy का उपयोग करें , यह एक बुनियादी खुला स्रोत ऐप है जो रिफ्लेक्टर के रूप में बहुत कुछ करता है
बाइनरी वॉरियर

1

cfeduke GetPEKind को कॉल करने की संभावना को नोट करता है। यह संभवतः PowerShell से ऐसा करना दिलचस्प है।

उदाहरण के लिए, एक cmdlet के लिए कोड है जिसका उपयोग किया जा सकता है: https://stackoverflow.com/a/16181743-64647

वैकल्पिक रूप से, https://stackoverflow.com/a/4719567/64257 पर ध्यान दिया जाता है कि "पावरशेल कम्युनिटी एक्सटेंशन में गेट-PEHeader cmdlet भी है जिसका उपयोग निष्पादन योग्य चित्रों के परीक्षण के लिए किया जा सकता है।"


1

इसके लिए एक और अधिक उन्नत एप्लिकेशन जो आप यहां पा सकते हैं: कोडप्लेक्स - एपिचेंज

उदाहरण:

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

0

पहले से उल्लेख किए गए टूल का एक विकल्प Telerik JustDecompile (फ्री टूल) है जो विधानसभा नाम के बगल में जानकारी प्रदर्शित करेगा:

टेलरिक में कोई भी या x86 या x64 जानकारी

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.