Как определить, была ли assembly .NET построена для x86 или x64?

У меня есть произвольный список compilationов .NET.

Мне нужно программно проверить, была ли построена каждая DLL для x86 (в отличие от x64 или Any CPU). Это возможно?

Посмотрите на System.Reflection.AssemblyName.GetAssemblyName(string assemblyFile)

Вы можете просмотреть метаданные сборки из возвращаемого экземпляра AssemblyName:

Использование PowerShell :

 [36] C: \> [reflection.assemblyname] :: GetAssemblyName ("$ {pwd} \ Microsoft.GLEE.dll") |  Флорида

 Имя: Microsoft.GLEE
 Версия: 1.0.0.0
 КультураИнфо:
 CodeBase: file: /// C: / projects / powershell / BuildAnalyzer / ...
 EscapedCodeBase: файл: /// C: / projects / powershell / BuildAnalyzer / ...
 ПроцессорАрхитектура: MSIL
 Флаги: PublicKey
 HashAlgorithm: SHA1
 VersionCompatibility: SameMachine
 KeyPair:
 FullName: Microsoft.GLEE, Version = 1.0.0.0, Culture = neut ... 

Здесь ProcessorArchitecture идентифицирует целевую платформу.

Я использую PowerShell в этом примере для вызова метода.

Вы можете использовать инструмент CLI CorFlags (например, C: \ Program Files \ Microsoft SDKs \ Windows \ v7.0 \ Bin \ CorFlags.exe), чтобы определить статус сборки на основе ее вывода и открытия сборки как бинарный актив, вы должны иметь возможность определить, где вам нужно определить, установлен ли флаг 32BIT в 1 ( x86 ) или 0 ( любой процессор или x64 , в зависимости от PE ):

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

Сообщение в блоге x64 Development с .NET содержит некоторую информацию о corflags .

Еще лучше, вы можете использовать Module.GetPEKind чтобы определить, является ли assembly значением PortableExecutableKinds PE32Plus (64-разрядная PE32Plus ), Required32Bit (32-разрядная и WOW) или ILOnly (любой процессор) вместе с другими атрибутами.

Только для уточнения, CorFlags.exe является частью .NET Framework SDK . У меня есть инструменты для разработки на моей машине, и самый простой способ для меня определить, является ли DLL 32-разрядной только:

  1. Откройте командную строку Visual Studio (в Windows: меню «Пуск / Программы / Microsoft Visual Studio / Visual Studio Tools / Visual Studio 2008 Command Prompt»)

  2. CD в ​​каталог, содержащий соответствующую DLL

  3. Запускать флагов: 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 

Согласно комментариям, вышеприведенные флаги должны быть прочитаны следующим образом:

  • Любой процессор: 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. 

Но с помощью этого метода он позволяет использовать возможности новых констант, просто подтвердите возврат, как вы сочтете нужным.

Попробуйте использовать CorFlagsReader из этого проекта в CodePlex . Он не имеет ссылок на другие сборки и может использоваться как есть.

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

Ниже приведен командный файл, который будет запускать corflags.exe всех dlls и exes в текущем рабочем каталоге и во всех подкаталогах, анализировать результаты и отображать целевую архитектуру каждого из них.

В зависимости от версии corflags.exe которая используется, позиции на выходе будут либо включать 32BIT , либо 32BITREQ32BITPREF ). Какой бы из этих двух не был включен в выход, это критическая позиция, которую нужно проверить, чтобы различать Any CPU и x86 . Если вы используете более раннюю версию corflags.exe (pre Windows SDK v8.0A), то в 32BIT будет присутствовать только 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. 

DotPeek от JetBrians обеспечивает быстрый и простой способ увидеть msil (anycpu), x86, x64 dotPeek

Еще один способ проверить целевую платформу сборки .NET – проверить сборку с помощью .NET Reflector …

@ # ~ # ~ €! Я только что понял, что новая версия не бесплатна! Итак, исправление, если у вас есть свободная версия рефлектора .NET, вы можете использовать его для проверки целевой платформы.

cfeduke отмечает возможность вызова GetPEKind. Это потенциально интересно сделать это от PowerShell.

Здесь, например, это код для командлета, который можно использовать: https://stackoverflow.com/a/16181743/64257

Кроме того, в https://stackoverflow.com/a/4719567/64257 отмечается, что «в расширениях сообщества PowerShell также используется командлет Get-PEHeader, который можно использовать для проверки исполняемых изображений».

Более продвинутое приложение для этого вы можете найти здесь: 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 

Еще один способ – использовать dumpbin из инструментов Visual Studio в DLL и искать соответствующий вывод

 dumpbin.exe /HEADERS  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  

Более общий способ – использовать структуру файлов для определения битов и типа изображения:

 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

Я клонировал супер удобный инструмент, который добавляет запись контекстного меню для ассемблеров в проводнике Windows, чтобы показать всю доступную информацию:

Загрузить здесь: https://github.com/tebjan/AssemblyInformation/releases

введите описание изображения здесь

  • Visual Studio 2010 не создает перед запуском при изменении кода
  • Определить версию сборки (CLR) сборки
  • Как ссылаться на сборки .NET с помощью PowerShell
  • Почему XCHG reg, reg 3 инструкции по микрооперации на современных архитектурах Intel?
  • как загрузить все сборки из вашего каталога / bin
  • Правильное изменение неопределенного поведения, если число больше ширины типа?
  • Сколько циклов процессора требуется для каждой инструкции сборки?
  • mscorlib.dll & System.dll
  • Использование разных версий одной и той же сборки в одной папке
  • Как сохранить сборки ASP.NET в AppDomain в живых?
  • Visual Studio «Не удалось скопировать» ... во время сборки
  • Interesting Posts
    Давайте будем гением компьютера.