Saya punya daftar arbitrer. NET rakitan.
Saya perlu memeriksa secara terprogram apakah setiap DLL dibangun untuk x86 (sebagai lawan dari x64 atau CPU apa pun). Apakah ini mungkin?
Saya punya daftar arbitrer. NET rakitan.
Saya perlu memeriksa secara terprogram apakah setiap DLL dibangun untuk x86 (sebagai lawan dari x64 atau CPU apa pun). Apakah ini mungkin?
Jawaban:
Melihat System.Reflection.AssemblyName.GetAssemblyName(string assemblyFile)
Anda dapat memeriksa metadata perakitan dari instance AssemblyName yang dikembalikan:
Menggunakan PowerShell :
[36] C: \> [reflection.assemblyname] :: GetAssemblyName ("$ {pwd} \ Microsoft.GLEE.dll") | fl Nama: Microsoft.GLEE Versi: 1.0.0.0 Info budaya: CodeBase: file: /// C: / proyek / PowerShell / BuildAnalyzer / ... EscapedCodeBase: file: /// C: / proyek / PowerShell / BuildAnalyzer / ... Prosesor Arsitektur: MSIL Bendera: PublicKey Algoritma Hash: SHA1 VersionCompatibility: SameMachine KeyPair: Nama Lengkap: Microsoft.GLEE, Versi = 1.0.0.0, Kultur = netral ...
Di sini, ProcessorArchitecture mengidentifikasi platform target.
Saya menggunakan PowerShell dalam contoh ini untuk memanggil metode.
[reflection.assemblyname]::GetAssemblyName("${pwd}\name.dll")
kadang-kadang direktori proses saat ini tidak sama dengan penyedia saat ini (yang mana saya menganggap DLL adalah untuk Anda)
// 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.
Sayangnya, tidak ada cara untuk membaca ProcessorArchitecture tanpa menggunakan GetName instance method
; menggunakan AssemblyName constructor
, bidang selalu diatur ke None
.
Anda dapat menggunakan alat CorFlags CLI (misalnya, C: \ Program Files \ Microsoft SDKs Windows \ v7.0 \ Bin \ CorFlags.exe) untuk menentukan status perakitan, berdasarkan outputnya dan membuka perakitan sebagai aset biner Anda harus dapat menentukan di mana Anda perlu mencari untuk menentukan apakah flag 32BIT diatur ke 1 ( x86 ) atau 0 ( Setiap CPU atau x64 , tergantung pada PE
):
Option | PE | 32BIT
----------|-------|---------
x86 | PE32 | 1
Any CPU | PE32 | 0
x64 | PE32+ | 0
Posting blog Pengembangan x64 dengan .NET memiliki beberapa informasi tentang corflags
.
Bahkan lebih baik, Anda dapat menggunakanModule.GetPEKind
untuk menentukan apakah suatu perakitan PortableExecutableKinds
bernilai PE32Plus
(64-bit), Required32Bit
(32-bit dan WOW), atau ILOnly
(CPU apa saja) bersama dengan atribut lainnya.
Hanya untuk klarifikasi, CorFlags.exe adalah bagian dari .NET Framework SDK . Saya memiliki alat pengembangan di komputer saya, dan cara paling sederhana bagi saya untuk menentukan apakah DLL hanya 32-bit adalah dengan:
Buka Visual Studio Command Prompt (Di Windows: menu Start / Programs / Microsoft Visual Studio / Visual Studio Tools / Visual Studio 2008 Command Prompt)
CD ke direktori yang berisi DLL yang dimaksud
Jalankan corflags seperti ini:
corflags MyAssembly.dll
Anda akan mendapatkan hasil seperti ini:
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
Sesuai komentar, bendera di atas harus dibaca sebagai berikut:
32BITREQ
dan 32BITPREF
bukannya 32BIT
nilai tunggal .
Bagaimana kalau Anda hanya menulis milik Anda sendiri? Inti dari arsitektur PE belum berubah secara serius sejak penerapannya pada Windows 95. Berikut ini adalah contoh 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;
}
}
Sekarang konstanta saat ini adalah:
0x10B - PE32 format.
0x20B - PE32+ format.
Tetapi dengan metode ini memungkinkan untuk kemungkinan konstanta baru, hanya memvalidasi pengembalian sesuai keinginan Anda.
Coba gunakan CorFlagsReader dari proyek ini di CodePlex . Itu tidak memiliki referensi ke majelis lain dan dapat digunakan apa adanya.
[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);
}
}
Di bawah ini adalah file batch yang akan berjalan corflags.exe
melawan semua dlls
dan exes
dalam direktori kerja saat ini dan semua sub-direktori, parsing hasil dan menampilkan arsitektur target masing-masing.
Bergantung pada versi corflags.exe
yang digunakan, item baris dalam output akan termasuk 32BIT
, atau 32BITREQ
(dan 32BITPREF
). Yang mana dari kedua ini yang termasuk dalam output adalah item baris kritis yang harus diperiksa untuk membedakan antara Any CPU
dan x86
. Jika Anda menggunakan versi yang lebih lama dari corflags.exe
(pra Windows SDK v8.0A), maka hanya 32BIT
item baris yang akan ada di output, seperti yang lain telah ditunjukkan dalam jawaban sebelumnya. Kalau tidak 32BITREQ
, 32BITPREF
ganti saja.
Asumsi corflags.exe
ini ada dalam %PATH%
. Cara paling sederhana untuk memastikan ini adalah dengan menggunakan a Developer Command Prompt
. Atau Anda dapat menyalinnya dari lokasi default itu .
Jika file batch di bawah ini dijalankan terhadap yang tidak dikelola dll
atau exe
, itu akan salah menampilkannya x86
, karena output aktual dari Corflags.exe
akan menjadi pesan kesalahan yang mirip dengan:
corflags: error CF008: File yang ditentukan tidak memiliki header terkelola yang valid
@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.
Satu cara lagi adalah dengan menggunakan dumpbin dari alat Visual Studio di DLL dan mencari output yang sesuai
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
Catatan: Di atas o / p untuk 32bit dll
Satu lagi opsi yang berguna dengan dumpbin.exe adalah / EKSPOR, Ini akan menunjukkan kepada Anda fungsi yang diekspos oleh dll
dumpbin.exe /EXPORTS <PATH OF THE DLL>
Cara yang lebih umum - gunakan struktur file untuk menentukan bitness dan tipe gambar:
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);
}
}
Enumerasi mode kompilasi
[Flags]
public enum CompilationMode
{
Invalid = 0,
Native = 0x1,
CLR = Native << 1,
Bit32 = CLR << 1,
Bit64 = Bit32 << 1
}
Kode sumber dengan penjelasan di GitHub
Saya telah mengkloning alat yang sangat berguna yang menambahkan entri menu konteks untuk majelis di windows explorer untuk menampilkan semua info yang tersedia:
Unduh di sini: https://github.com/tebjan/AssemblyInformation/releases
Cara lain untuk memeriksa platform target rakitan .NET adalah memeriksa rakitan dengan .NET Reflector ...
@ # ~ # € ~! Saya baru sadar bahwa versi baru itu tidak gratis! Jadi, koreksi, jika Anda memiliki versi gratis .NET reflector, Anda dapat menggunakannya untuk memeriksa platform target.
cfeduke mencatat kemungkinan memanggil GetPEKind. Ini berpotensi menarik untuk melakukan ini dari PowerShell.
Di sini, misalnya, adalah kode untuk cmdlet yang dapat digunakan: https://stackoverflow.com/a/16181743/64257
Atau, di https://stackoverflow.com/a/4719567/64257 dicatat bahwa "ada juga cmdlet Get-PEHeader di PowerShell Community Extensions yang dapat digunakan untuk menguji gambar yang dapat dieksekusi."
Aplikasi yang lebih canggih untuk itu dapat Anda temukan di sini: CodePlex - ApiChange
Contoh:
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
Alternatif untuk alat yang telah disebutkan adalah Telerik JustDecompile (alat gratis) yang akan menampilkan informasi di sebelah nama majelis: