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

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

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


person Judah Gabriel Himango    schedule 06.11.2008    source источник
comment
возможный дубликат Как определить, для какой платформы исполняемый файл скомпилирован?   -  person nawfal    schedule 25.02.2013
comment
Вы также можете проверить это: check- if-unmanaged-dll-is-32-or-64-bit.   -  person Matt    schedule 11.05.2015
comment
В более поздней версии CorFlags, соответствующей .NET 4.5, 32BIT был заменен на 32BITREQ и 32BITPREF..   -  person Peter Mortensen    schedule 28.06.2015
comment


Ответы (16)


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

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

Используя PowerShell:

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

Name                  : Microsoft.GLEE
Version               : 1.0.0.0
CultureInfo           :
CodeBase              : file:///C:/projects/powershell/BuildAnalyzer/...
EscapedCodeBase       : file:///C:/projects/powershell/BuildAnalyzer/...
ProcessorArchitecture : MSIL
Flags                 : PublicKey
HashAlgorithm         : SHA1
VersionCompatibility  : SameMachine
KeyPair               :
FullName              : Microsoft.GLEE, Version=1.0.0.0, Culture=neut... 

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

  • Amd64: 64-разрядный процессор на базе архитектуры x64.
  • Arm: процессор ARM.
  • IA64: только 64-разрядный процессор Intel Itanium.
  • MSIL: нейтральный по отношению к процессору и количеству бит на слово.
  • X86: 32-разрядный процессор Intel, собственный или в среде Windows в Windows на 64-разрядной платформе (WOW64).
  • Нет: неизвестное или неопределенное сочетание процессора и количества бит на слово.

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

person x0n    schedule 06.11.2008
comment
Простите за глупый вопрос - но что в этом вам говорит, что это x86? - person George Mauer; 13.12.2012
comment
Поле ProcessorArchitecture - это перечисление; в приведенном выше примере он установлен на MSIL, что означает нейтральный по отношению к процессору и битам на слово. Другие значения включают X86, IA64, Amd64. См. msdn.microsoft.com/en-us/library/ для более подробной информации. - person Brian Gillespie; 13.12.2012
comment
Я получаю следующую ошибку при попытке использовать PowerShell: Exception calling "GetAssemblyName" with "1" argument(s): "Could not load file or assembly '[DLLName].dll' or one of its dependencies. The system cannot find the file specified." (Да, я написал это правильно). - person PeterX; 29.10.2013
comment
Попробуйте использовать [reflection.assemblyname]::GetAssemblyName("${pwd}\name.dll"), поскольку иногда текущий каталог процесса не совпадает с каталогом текущего провайдера (я предполагаю, что именно здесь DLL для вас) - person x0n; 29.10.2013
comment
Еще одно предостережение, на которое следует обратить внимание, - это забыть разблокировать DLL, если вы загрузили ее из Интернета. Используйте unblock-файл или щелкните правой кнопкой мыши / свойства / разблокировать из проводника. Вам нужно будет перезапустить оболочку, чтобы она распознала статус разблокировки, если вы уже потерпели неудачу один раз в текущем сеансе (вините в этом Internet Explorer - да, действительно). - person x0n; 23.01.2014
comment
Что лучше: AssemblyName.ProcessorArchitecture, CorFlags или программа чтения PE stackoverflow.com/a/9767750/206730? - person Kiquenet; 25.03.2014
comment
В коде 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. - person metadings; 13.08.2014
comment
Как это работает, если файл exe / com / dll создан не с использованием .NET framework? Примером может быть write.exe из Windows 95, win386.dll из Windows 3.1 или himem.sys из DOS 6.x. - person Kraang Prime; 06.08.2016
comment
@SamuelJackson Вопрос явно квалифицирует ввод как сборку .NET. Если это не так, это другой вопрос. Код не сможет загрузить DLL и вызовет исключение. - person x0n; 08.08.2016

Вы можете использовать CorFlags инструмент CLI (например, 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 с .NET содержит некоторую информацию о corflags.

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

person cfeduke    schedule 06.11.2008
comment
После просмотра вашего обновления использование GetPEKind кажется правильным способом сделать это. Я пометил ваш как ответ. - person Judah Gabriel Himango; 07.11.2008
comment
Отличный отзыв о Module.GetPEKind, о котором до сих пор не знал. Я всегда использовал инструмент corflags. - person Scott Dorman; 15.08.2009
comment
GetPEKind не работает в 64-битном процессе при проверке 32-битных сборок - person jjxtra; 19.04.2010
comment
Вы должны вызвать GetPEKind из 32-битного процесса - person Ludwo; 18.02.2013
comment
Я устанавливаю VS 2008, VS 2010, VS 2012 и VS 2013. У меня есть 8 файлов CorFlags.exe в подпапках в C: \ Program Files (x86) \ Microsoft SDKs \ Windows \. Что я должен использовать? - person Kiquenet; 25.03.2014
comment
md5sum каждый исполняемый файл, чтобы увидеть, отличаются ли какие-либо из них (или просто проверьте размер файла и дату изменения); Я подозреваю, что любой из них будет работать нормально. - person cfeduke; 25.03.2014
comment
Размер файла @cfeduke отличается для обеих версий - person Kiquenet; 25.03.2014
comment
@Ludwo любой образец полного исходного кода с использованием GetPEKind из 32-битного процесса ?. PsychoDad сообщает, что GetPEKind не работает в 64-битном процессе при проверке 32-битных сборок - person Kiquenet; 26.03.2014
comment
Проверьте мой ответ ниже - person Ludwo; 26.03.2014
comment
Как указано в этом ответе, в .NET 4.5 вместо флага 32BIT используется 32BITREQ и 32BITPREF. PE32 / 0/0 и PE32 / 0/1 являются предпочтительными для AnyCPU и AnyCPU 32-bit соответственно. - person angularsen; 30.01.2015
comment
Это просто показывает ошибку: не является допустимым приложением Win32. - person O. R. Mapper; 10.03.2015

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

  1. Откройте командную строку Visual Studio (в Windows: меню Пуск / Программы / Microsoft Visual Studio / Инструменты Visual Studio / Командная строка 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

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

  • Любой процессор: PE = PE32 и 32BIT = 0
  • x86: PE = PE32 и 32BIT = 1
  • 64-разрядная версия: PE = PE32 + и 32BIT = 0
person JoshL    schedule 16.06.2009
comment
Между тем это, кажется, изменилось; corflags теперь отображает 32BITREQ и 32BITPREF, а не одно значение 32BIT. - person O. R. Mapper; 10.03.2015
comment
Microsoft .NET 4.5 представила новую опцию, Любой 32-разрядный процессор предпочтительнее. Подробности Здесь. - person RBT; 10.04.2017
comment
Командная строка Visual Studio в настоящее время называется Командная строка разработчика Visual Studio 2019. - person Uwe Keim; 27.10.2019

Как насчет того, чтобы написать свое собственное? Ядро архитектуры 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.

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

person Jason    schedule 19.03.2012
comment
Интересно, спасибо за код с пояснением. Module.GetPEKind, вероятно, самый простой путь. Но это полезно для обучения. Спасибо. - person Judah Gabriel Himango; 19.03.2012
comment
Очень интересно, но когда у меня есть приложение, скомпилированное на Any CPU, результат 0x10B. Это неправильно, потому что мое приложение работает в системе x64. Есть ли другой флаг, который нужно проверить? - person Samuel; 24.07.2012
comment
GetPEArchitecture работает для сборок, скомпилированных с использованием .net 3.5, 4.0, 4.5 и 4.5.1? В любом случае, я думаю, Module.GetPEKind не работает в 64-битном процессе при проверке 32-битных сборок. - person Kiquenet; 26.03.2014

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

person Prabhakaran Rajagopal    schedule 22.08.2017

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

person Ludwo    schedule 18.02.2013
comment
Это наиболее точный и полезный ответ. - person Kirill Osenkov; 25.03.2013
comment
Ссылка все еще работает на момент написания этой статьи, но, поскольку CodePlex скоро будет закрыт, было бы хорошо предпринять соответствующие действия, пока не стало слишком поздно. - person Peter Mortensen; 18.06.2017

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

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

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

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

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

person thalm    schedule 18.08.2018
comment
В исходном коде (zip) для загрузки есть файл проекта, содержащий жестко заданные пути к файлам на вашем компьютере и не включенный в загрузку :( - person Ben Voigt; 31.07.2020

Еще один способ - использовать 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

Примечание: вышеупомянутое значение o / p предназначено для 32-битной библиотеки DLL.

Еще один полезный параметр с dumpbin.exe - / EXPORTS, он покажет вам функцию, предоставляемую dll.

dumpbin.exe /EXPORTS <PATH OF THE DLL>
person Ayush joshi    schedule 28.07.2017

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

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

person BlackGad    schedule 27.03.2018

Другой способ проверить целевую платформу сборки .NET - это проверить сборку с помощью .NET Reflector. ...

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

person sakito    schedule 04.08.2011
comment
Используйте ILSpy, это базовое приложение с открытым исходным кодом, которое выполняет те же функции, что и Reflector. - person Binary Worrier; 05.08.2011

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

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

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

person Chris    schedule 24.04.2013

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

Альтернативой уже упомянутым инструментам является Telerik JustDecompile (бесплатный инструмент), который отображает информацию рядом с названием сборки:

Любая информация или информация о x86 или x64 в Telerik

person Alexei - check Codidact    schedule 19.05.2020

Мне нравится инструмент ILSpy. Он показывает не только архитектуру, но и целевой фреймворк:

// linq2db, Version=3.0.0.0, Culture=neutral, PublicKeyToken=e41013125f9e410a
// Global type: <Module>
// Architecture: AnyCPU (64-bit preferred)
// Runtime: v4.0.30319
// This assembly is signed with a strong name key.
// This assembly was compiled using the /deterministic option.
// Hash algorithm: SHA1

Таким образом, можно определить, является ли это .Net Core 2.1, .Net Framework 4.6 или любой другой:

целевая платформа

person Maxim    schedule 14.04.2021

person    schedule
comment
Спасибо за это, одно из наших приложений должно быть построено как x86, добавление модульного теста гарантирует, что библиотеки сборки сервера сборки будут 32-битными, и избежать этих ошибок :) - person Mido; 05.03.2015