У мене є довільний перелік .NET-збірок.
Мені потрібно програмно перевірити, чи була створена кожна DLL для x86 (на відміну від x64 чи будь-якого процесора). Чи можливо це?
У мене є довільний перелік .NET-збірок.
Мені потрібно програмно перевірити, чи була створена кожна DLL для x86 (на відміну від x64 чи будь-якого процесора). Чи можливо це?
Відповіді:
Подивись на System.Reflection.AssemblyName.GetAssemblyName(string assemblyFile)
Ви можете вивчити метадані збирання з поверненого екземпляра AssemblyName:
Використання PowerShell :
[36] C: \> [reflex.assemblyname] :: GetAssemblyName ("$ {pwd} \ Microsoft.GLEE.dll") | ет Ім'я: Microsoft.GLEE Версія: 1.0.0.0 КультураІнфо: CodeBase: файл: /// C: / проекти / повноваження / BuildAnalyzer / ... EscapedCodeBase: файл: /// C: / Проекти / powershell / BuildAnalyzer / ... Процесорна архітектура: MSIL Прапори: PublicKey HashAlgorithm: SHA1 VersionCompatibility: SameMachine KeyPair: FullName: Microsoft.GLEE, версія = 1.0.0.0, культура = нейт ...
Тут ProcessorArchitecture визначає цільову платформу.
У цьому прикладі я використовую PowerShell для виклику методу.
[reflection.assemblyname]::GetAssemblyName("${pwd}\name.dll")
як іноді поточний каталог процесу не такий, як поточний провайдер (саме там я припускаю, що DLL призначений для вас)
// 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
.
Ви можете використовувати інструмент 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
щоб визначити, чи збірка є PortableExecutableKinds
значенням PE32Plus
(64-бітним), Required32Bit
(32-бітним і WOW), або ILOnly
(будь-яким процесором) разом з іншими атрибутами.
Тільки для уточнення CorFlags.exe є частиною .NET Framework SDK . На моїй машині у мене є інструменти розробки, і найпростіший спосіб визначити, чи є DLL 32-бітним, це:
Відкрийте командний рядок Visual Studio (У Windows: меню Пуск / Програми / Microsoft Visual Studio / Інструменти Visual Studio / Командний рядок Visual Studio 2008)
Компакт-диск до каталогу, що містить відповідну DLL
Виконайте такі корфлаги:
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
значення.
Як щодо того, що ти просто пишеш, що ти власний? Ядро архітектури 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
, або 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.
Ще один спосіб - використовувати 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 - / ЕКСПОРТ, він покаже вам функцію, яку зазнає dllbin
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
Я клонував надзвичайно зручний інструмент, який додає запис у контекстне меню для збірок у провіднику Windows, щоб показати всю наявну інформацію:
Завантажте тут: https://github.com/tebjan/AssemblyInformation/releases
Ще один спосіб перевірити цільову платформу .NET збірки - це перевірка складання за допомогою .NET Reflector ...
@ # ~ # € ~! Я щойно зрозумів, що нова версія не безкоштовна! Отже, виправлення, якщо у вас є безкоштовна версія рефлектора .NET, ви можете використовувати його для перевірки цільової платформи.
cfeduke відзначає можливість виклику GetPEKind. Це можливо зробити цікаво від PowerShell.
Ось, наприклад, код для командлета, який можна використовувати: https://stackoverflow.com/a/16181743/64257
Крім того, на веб-сторінці https://stackoverflow.com/a/4719567/64257 зазначається, що "в розширеннях PowerShell Community також існує командлет 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
Альтернативою вже згаданим інструментам є Telerik JustDecompile (безкоштовний інструмент), який відображатиме інформацію поруч із назвою збірки: