У меня есть произвольный список сборок .NET.
Мне нужно программно проверить, была ли каждая DLL создана для x86 (в отличие от x64 или любого процессора). Это возможно?
У меня есть произвольный список сборок .NET.
Мне нужно программно проверить, была ли каждая DLL создана для x86 (в отличие от x64 или любого процессора). Это возможно?
Посмотрите на 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 идентифицирует целевую платформу.
В этом примере я использую 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
[reflection.assemblyname]::GetAssemblyName("${pwd}\name.dll")
, поскольку иногда текущий каталог процесса не совпадает с каталогом текущего провайдера (я предполагаю, что именно здесь DLL для вас)
- person x0n; 29.10.2013
// 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
write.exe
из Windows 95, win386.dll
из Windows 3.1 или himem.sys
из DOS 6.x.
- person Kraang Prime; 06.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
.
corflags
.
- person Scott Dorman; 15.08.2009
md5sum
каждый исполняемый файл, чтобы увидеть, отличаются ли какие-либо из них (или просто проверьте размер файла и дату изменения); Я подозреваю, что любой из них будет работать нормально.
- person cfeduke; 25.03.2014
Просто для пояснения: CorFlags.exe является частью .NET Framework SDK. У меня есть инструменты разработки на моем компьютере, и самый простой способ определить, является ли DLL только 32-разрядной, - это:
Откройте командную строку Visual Studio (в Windows: меню Пуск / Программы / Microsoft Visual Studio / Инструменты Visual Studio / Командная строка Visual Studio 2008)
CD в каталог, содержащий рассматриваемую DLL
Запустите 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
В соответствии с комментариями указанные выше флаги следует читать следующим образом:
32BITREQ
и 32BITPREF
, а не одно значение 32BIT
.
- person O. R. Mapper; 10.03.2015
Как насчет того, чтобы написать свое собственное? Ядро архитектуры 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. Он не имеет ссылок на другие сборки и может использоваться как есть.
Ниже приведен командный файл, который будет запускать corflags.exe
для всех dlls
и exes
в текущем рабочем каталоге и всех подкаталогах, анализировать результаты и отображать целевую архитектуру каждого из них.
В зависимости от используемой версии corflags.exe
строки вывода будут включать либо 32BIT
, , либо 32BITREQ
(и 32BITPREF
). Какой из этих двух вариантов включен в выходные данные, является критически важным элементом строки, который необходимо проверить, чтобы различать 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.
Я клонировал очень удобный инструмент, который добавляет пункт контекстного меню для сборок в проводнике Windows, чтобы показать всю доступную информацию:
Загрузите здесь: https://github.com/tebjan/AssemblyInformation/releases
Еще один способ - использовать 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>
Более общий способ - использовать файловую структуру для определения разрядности и типа изображения:
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
Другой способ проверить целевую платформу сборки .NET - это проверить сборку с помощью .NET Reflector. ...
@ # ~ # € ~! Я только что понял, что новая версия не бесплатна! Итак, исправление, если у вас есть бесплатная версия рефлектора .NET, вы можете использовать ее для проверки целевой платформы.
cfeduke отмечает возможность вызова GetPEKind. Это потенциально интересно сделать из PowerShell.
Вот, например, код для командлета, который можно использовать: https://stackoverflow.com/a/16181743/64257 а>
В качестве альтернативы, на странице https://stackoverflow.com/a/4719567/64257 отмечается, что «есть также Get- Командлет PEHeader в расширениях сообщества PowerShell, который можно использовать для проверки наличия исполняемых образов ".
Более продвинутое приложение для этого можно найти здесь: 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
Альтернативой уже упомянутым инструментам является Telerik JustDecompile (бесплатный инструмент), который отображает информацию рядом с названием сборки:
Мне нравится инструмент 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 или любой другой: