Bir .NET derlemesinin x86 veya x64 için oluşturulmuş olup olmadığını nasıl belirleyebilirim?


327

.NET derlemelerinin rasgele bir listesi var.

Programlı olarak her DLL x86 (x64 veya herhangi bir CPU aksine) için inşa edilmiş olup olmadığını denetlemeniz gerekir. Mümkün mü?



2
Ayrıca bunu kontrol etmek isteyebilirsiniz: check-if-manmaned-dll-is-32-bit-veya-64-bit .
Matt

2
.NET 4.5'e karşılık gelen CorFlags'ın sonraki sürümlerinde "32BIT", "32BITREQ" ve "32BITPREF" ile değiştirildi. .
Peter Mortensen

Yanıtlar:


281

Bakmak System.Reflection.AssemblyName.GetAssemblyName(string assemblyFile)

Derleme meta verilerini döndürülen AssemblyName örneğinden inceleyebilirsiniz:

PowerShell'i kullanma :

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

İsim: Microsoft.GLEE
Sürüm: 1.0.0.0
CultureInfo:
CodeBase: dosya: /// C: / projects / powershell / BuildAnalyzer / ...
EscapedCodeBase: dosya: /// C: / projects / powershell / BuildAnalyzer / ...
İşlemci Mimarisi: MSIL
Bayraklar: PublicKey
HashAlgoritma: SHA1
Sürüm Uyumluluğu: SameMachine
KeyPair:
FullName: Microsoft.GLEE, Sürüm = 1.0.0.0, Kültür = nöt ... 

Burada, ProcessorArchitecture hedef platformu tanımlar.

  • Amd64 : x64 mimarisini temel alan 64 bit işlemci.
  • Arm : Bir ARM işlemci.
  • IA64 : Yalnızca 64 bit Intel Itanium işlemci.
  • MSIL : İşlemci ve sözcük başına bit bakımından nötr.
  • X86 : 64 bit bir platformda (WOW64) yerel veya Windows ortamında Windows ortamında bulunan 32 bit Intel işlemci.
  • Yok : Bilinmeyen veya belirtilmemiş bir işlemci ve sözcük başına bit kombinasyonu.

Bu örnekte yöntemi çağırmak için PowerShell kullanıyorum.


60
Aptal soruyu affedin - ama bunun size x86 olduğunu söyleyen şey nedir?
George Mauer

53
İşlemci Mimarisi alanı bir numaralandırmadır; yukarıdaki örnekte MSIL olarak ayarlanmıştır, bu da "işlemci ve kelime başına bit başına göre nötr" anlamına gelir. Diğer değerler X86, IA64, Amd64'ü içerir. Daha fazla bilgi için msdn.microsoft.com/en-us/library/… adresine bakın .
Brian Gillespie

4
İle deneyin [reflection.assemblyname]::GetAssemblyName("${pwd}\name.dll")bazen sürecin geçerli dizin değil aynı şekilde (Ben DLL size göre farz olan) geçerli sağlayıcısının
x0n

2
Dikkat edilmesi gereken başka bir uyarı, internet'lerden indirdiyseniz DLL'nin "engelini kaldırmayı" unutmaktır. Engellemeyi kaldırma dosyasını kullanın veya explorer'dan / properties / engellemeyi kaldırın. Geçerli oturumda bir kez başarısız olduysanız, engellenmemiş durumu tanıması için kabuğu yeniden başlatmanız gerekir (bunun için internet explorer'ı
suçlayın

1
ASP.NET MVC kodunda bir yorum var // 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.Ne yazık ki, ProcessorArchitecture kullanmadan okumak için hiçbir yolu yoktur GetName instance method; kullanarak AssemblyName constructor, alan her zaman olarak ayarlanır None.
metadings

221

CorFlags'ı kullanabilirsiniz CLI aracı (örneğin, C: \ Program Files \ Microsoft SDK'leri \ Windows \ v7.0 \ Bin \ CorFlags.exe) durumunu belirlemek için bir montaj, kendi çıkışında ve a olarak montaj bir açılış dayalı 32BIT bayrağının 1 ( x86 ) veya 0 ( bağlı olarak herhangi bir CPU veya x64 ) olarak ayarlanıp ayarlanmadığını belirlemek için nerede aramanız gerektiğini belirleyebilmeniz gerekir PE:

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

.NET ile x64 Geliştirme blog yazısı hakkında bazı bilgiler var corflags.

Daha da iyisi, yapabilirsiniz kullanmakModule.GetPEKind bir montaj olup olmadığını belirlemek içinPortableExecutableKinds diğer niteliklerle birlikte değer PE32Plus(64 bit), Required32Bit(32 bit ve WOW) veya ILOnly(herhangi bir CPU) .


1
Güncellemenizi gördükten sonra, GetPEKind kullanmak bunu yapmanın doğru yolu gibi görünüyor. Sizinkinin cevabı olarak işaretledim.
Judah Gabriel Himango

9
32 bit derlemeleri kontrol ederken 64 bit işleminde GetPEKind başarısız oluyor
jjxtra

2
32bit işleminden GetPEKind'i aramak zorundasınız
Ludwo

2
VS 2008, VS 2010, VS 2012 ve VS 2013 yüklüyorum. C: \ Program Files (x86) \ Microsoft SDKs \ Windows \ alt klasörlerinde 8 dosya CorFlags.exe var. Hangisini kullanmalıyım?
Kiquenet

5
İşaret edildiği gibi bu cevap , .NET 4.5 32BITREQ ve 32BITPREF yerine 32BIT bayrağı vardır. PE32 / 0/0 ve PE32 / 0/1, sırasıyla AnyCPU ve AnyCPU 32-bit tercih edilir.
angularsen

141

Sadece açıklama amacıyla, CorFlags.exe .NET Framework SDK'sının bir parçasıdır . Benim makine geliştirme araçları var ve benim için bir DLL 32-bit olup olmadığını belirlemek için en basit yolu:

  1. Visual Studio Komut İstemi'ni açın (Windows'ta: Başlat / Programlar / Microsoft Visual Studio / Visual Studio Araçları / Visual Studio 2008 Komut İstemi menüsü)

  2. Söz konusu DLL dosyasını içeren dizine CD

  3. Corflags'ı şu şekilde çalıştırın: corflags MyAssembly.dll

Bunun gibi bir çıktı elde edersiniz:

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

Yorumlara göre yukarıdaki bayraklar aşağıdaki gibi okunmalıdır:

  • Herhangi bir CPU: PE = PE32 ve 32BIT = 0
  • x86: PE = PE32 ve 32BIT = 1
  • 64 bit: PE = PE32 + ve 32BIT = 0

12
Bu arada değişmiş gibi görünüyor; Şimdi görüntüler corflags 32BITREQve 32BITPREFyerine tek bir 32BITdeğer.
VEYA Haritacı

1
Microsoft .NET 4.5 yeni bir seçenek tanıttı, Herhangi bir CPU 32-bit Tercihli. İşte detaylar.
RBT

"Visual Studio Komut İstemi" günümüzde " Visual Studio 2019 Geliştirici Komut İstemi " olarak adlandırılmaktadır.
Uwe Keim

22

Sadece kendi yazdığın nasıl? PE mimarisinin çekirdeği Windows 95'teki uygulamasından bu yana ciddi bir şekilde değişmedi. İşte bir C # örneği:

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

Şimdi mevcut sabitler:

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

Ancak bu yöntemle yeni sabitlerin olasılıklarına izin verir, sadece uygun gördüğünüz gibi dönüşü doğrulayın.


1
İlginç, açıklamalı kod için teşekkürler. Module.GetPEKind muhtemelen en kolay yoldur. Ama bu öğrenme uğruna faydalıdır. Teşekkürler.
Judah Gabriel Himango

3
Çok ilginç ama herhangi bir CPU ile derlenmiş bir uygulama olduğunda, sonuç 0x10B olur. Uygulamam x64 sisteminde çalıştırıldığı için bu yanlış. Kontrol edilecek başka bayrak var mı?
Samuel

GetPEArchitecture .net 3.5, 4.0, 4.5 ve 4.5.1 kullanılarak derlenen montajlar için çalışır? Her neyse, bence, Module.GetPEKind 32 bit derlemeleri kontrol ederken 64 bit işlemde başarısız oluyor.
Kiquenet

9

CodePlex bu projeden CorFlagsReader kullanmaya çalışın . Diğer montajlara referansları yoktur ve olduğu gibi kullanılabilir.


1
Bu en doğru ve yararlı cevap.
Kirill Osenkov

Bağlantı hala bu yazıdan itibaren çalışıyor, ancak CodePlex kapatılmak üzereyken, çok geç olmadan uygun eylemi yapmak iyi olurdu.
Peter 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);
    }
}

Bunun için teşekkürler, Uygulamalarımızdan biri x86 olarak oluşturulmalı, birim testi ekleyerek yapı sunucusunun yapı kitaplıklarının 32 bit olmasını sağlar ve bu hataların olmasını önler :)
Mido

5

Aşağıda çalışacak bir toplu iş dosyasıdır corflags.exetüm karşı dllsve exesgeçerli çalışma dizini ve tüm alt dizinlerde, sonuçlarını ayrıştırmak ve her hedef mimarisini gösterir.

Sürümüne bağlı corflags.exeolduğunu çıktıda satır öğeleri ya içerecektir kullanılır 32BIT, ya da 32BITREQ (ve 32BITPREF). Bu ikisinden hangisi çıktıya dahil edilirse, Any CPUve arasında ayrım yapmak için kontrol edilmesi gereken kritik satır öğesidir x86. Eski bir corflags.exeWindows sürümü kullanıyorsanız (Windows SDK v8.0A öncesi), 32BITgeçmiş yanıtlarda belirtildiği gibi, çıktıda yalnızca satır öğesi bulunur. Aksi halde 32BITREQve 32BITPREFdeğiştirin.

Bu varsayar corflags.exeiçindedir %PATH%. Bunu sağlamanın en basit yolu a kullanmaktır Developer Command Prompt. Alternatif olarak, varsayılan konumundan kopyalayabilirsiniz .

Aşağıdaki toplu iş dosyası yönetilmeyen bir dosyaya karşı çalıştırılırsa dllveya exehatalı olarak görüntülenir x86, çünkü gerçek çıktı Corflags.exe, aşağıdakine benzer bir hata iletisi olacaktır:

corflags: hata CF008: Belirtilen dosyanın geçerli bir yönetilen başlığı yok

@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

Başka bir yol DLL üzerinde Visual Studio araçlarından dumpbin kullanmak ve uygun çıktı aramak için olurdu

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

Not: o / p üstü 32bit dll içindir

Dumpbin.exe ile bir başka kullanışlı seçenek / EXPORTS, dll tarafından maruz bırakılan işlevi gösterecektir

dumpbin.exe /EXPORTS <PATH OF THE DLL>

2

Daha genel bir yol - bitlik ve görüntü türünü belirlemek için dosya yapısını kullanın:

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

Derleme modu numaralandırması

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

GitHub'da açıklamalı kaynak kodu



1

Bir .NET derlemesinin hedef platformunu denetlemenin başka bir yolu, derlemeyi .NET Reflector ile denetlemektir ...

@ # ~ # € ~! Yeni sürümün ücretsiz olmadığını fark ettim! Yani, düzeltme, .NET reflektörün ücretsiz bir sürümüne sahipseniz, bunu hedef platformu kontrol etmek için kullanabilirsiniz.


9
ILSpy kullanın , Reflector ile aynı şeyleri yapan basit bir açık kaynak uygulaması
Binary Worrier


1

Bunun için daha gelişmiş bir uygulama burada bulabilirsiniz: CodePlex - ApiChange

Örnekler:

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.