我有一个C#程序,需要通过用户提供的dll复制另一个程序才能加载和使用。如果程序在64位机器上运行,则不应允许用户传递32位dll并且应该通知用户他们提供了不正确的dll。那我怎样才能找到一个dll的架构?
我看到了几个类似的问题他们提到了DUMPBIN和Corflags.exe,但是没有示例代码,那么我在哪里可以找到这些程序以及如何使用它们?
答案 0 :(得分:5)
这是C#
控制台应用程序的完整代码,可以检测dll
架构,其中也包含您想要的架构。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
MachineType type = GetDllMachineType("path/to/MyAssembly.dll");
if (type.Equals(MachineType.IMAGE_FILE_MACHINE_I386))
{
Console.WriteLine("Dll architecture: x86/32bit");
}
else if (type.Equals(MachineType.IMAGE_FILE_MACHINE_IA64))
{
Console.WriteLine("Dll architecture: x64/64bit");
}
Console.ReadKey();
}
public static MachineType GetDllMachineType(string dllPath)
{
//see http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx
//offset to PE header is always at 0x3C
//PE header starts with "PE\0\0" = 0x50 0x45 0x00 0x00
//followed by 2-byte machine type field (see document above for enum)
FileStream fs = new FileStream(dllPath, FileMode.Open, FileAccess.Read);
BinaryReader br = new BinaryReader(fs);
fs.Seek(0x3c, SeekOrigin.Begin);
Int32 peOffset = br.ReadInt32();
fs.Seek(peOffset, SeekOrigin.Begin);
UInt32 peHead = br.ReadUInt32();
if (peHead != 0x00004550) // "PE\0\0", little-endian
throw new Exception("Can't find PE header");
MachineType machineType = (MachineType)br.ReadUInt16();
br.Close();
fs.Close();
return machineType;
}
public enum MachineType : ushort
{
IMAGE_FILE_MACHINE_UNKNOWN = 0x0,
IMAGE_FILE_MACHINE_AM33 = 0x1d3,
IMAGE_FILE_MACHINE_AMD64 = 0x8664,
IMAGE_FILE_MACHINE_ARM = 0x1c0,
IMAGE_FILE_MACHINE_EBC = 0xebc,
IMAGE_FILE_MACHINE_I386 = 0x14c,
IMAGE_FILE_MACHINE_IA64 = 0x200,
IMAGE_FILE_MACHINE_M32R = 0x9041,
IMAGE_FILE_MACHINE_MIPS16 = 0x266,
IMAGE_FILE_MACHINE_MIPSFPU = 0x366,
IMAGE_FILE_MACHINE_MIPSFPU16 = 0x466,
IMAGE_FILE_MACHINE_POWERPC = 0x1f0,
IMAGE_FILE_MACHINE_POWERPCFP = 0x1f1,
IMAGE_FILE_MACHINE_R4000 = 0x166,
IMAGE_FILE_MACHINE_SH3 = 0x1a2,
IMAGE_FILE_MACHINE_SH3DSP = 0x1a3,
IMAGE_FILE_MACHINE_SH4 = 0x1a6,
IMAGE_FILE_MACHINE_SH5 = 0x1a8,
IMAGE_FILE_MACHINE_THUMB = 0x1c2,
IMAGE_FILE_MACHINE_WCEMIPSV2 = 0x169,
}
// returns true if the dll is 64-bit, false if 32-bit, and null if unknown
public static bool? UnmanagedDllIs64Bit(string dllPath)
{
switch (GetDllMachineType(dllPath))
{
case MachineType.IMAGE_FILE_MACHINE_AMD64:
case MachineType.IMAGE_FILE_MACHINE_IA64:
return true;
case MachineType.IMAGE_FILE_MACHINE_I386:
return false;
default:
return null;
}
}
}
}
你写过关于此的内容,而且,只是要知道,这将有助于您获得有关装配的一些信息(dll
),但这不是C#
!这是一个可以在Visual Studio
控制台中使用的工具。
只需打开Visual Studio
控制台并使用此命令:
C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC>corflags C:/path/to/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 : 24 ILONLY : 0 32BIT : 0 Signed : 1
然后,专注于PE:PE32
,这将描述您的装配体系结构:
所以,据此......
AnyCPU 表示 - > PE:PE32 - > 32BIT:0
x86 表示 - > PE:PE32 - > 32BIT:1
x64 表示 - > PE:PE32 + - > 32BIT:0
MyAssembly.dll
的架构是32bit
好吧,如果你想简化所有这些,一个想法可能是使用C#
创建一个后台进程然后在参数中使用我上面给你的命令并打印PE:XX
的输出到获得程序集架构并根据该值告诉应用程序该做什么。
我刚做了一些研究,希望这会有所帮助: - )
答案 1 :(得分:3)
前段时间我们想在构建中运行64位混合模式单元测试而不改变构建环境。我写了一个工具,使用反射发射创建代理程序集。这是我写的实用程序类,它检测程序集是否为64位。这与corflags控制的标志不同
命名空间MstestRunner.TestProxyGenerator { 使用系统; 使用System.Globalization; 使用System.IO; 使用System.Reflection;
/// <summary>
/// TODO: Update summary.
/// </summary>
public static class AssemblyUtility
{
/// <summary>
/// The value 'PE\0\0'
/// </summary>
private const uint PeHeaderValue = 0x4550;
/// <summary>
/// Image file value found at start of PE header that indicates assembly is 64bit.
/// </summary>
private const ushort ImageFileMachineAmd64 = 0x8664;
/// <summary>
/// The offset to PIMAGE_DOS_HEADER->e_lfanew
/// </summary>
private const int DosHeaderLfaNewOffset = 0x3c;
/// <summary>
/// Checks to see if the module is a 64 bit
/// </summary>
/// <param name="path">The path to the assembly.</param>
/// <returns>
/// True if is 64bit
/// </returns>
public static bool Is64BitImage(string path)
{
return ReadImageMachineType(path) == MachineType.ImageFileMachineAMD64;
}
/// <summary>
/// Reads the machine type from the pe header.
/// </summary>
/// <param name="path">The path to the image.</param>
/// <returns>The assembly machinetype.</returns>
public static MachineType ReadImageMachineType(string path)
{
// The memory layout varies depending on 32/64 bit. The portions of the PE header we are reading should be the same though regardless.
byte[] buffer = new byte[4];
using (FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read))
{
// skip to PIMAGE_DOS_HEADER->e_lfanew of dos header.
fileStream.Seek(DosHeaderLfaNewOffset, SeekOrigin.Begin);
// read and jump to offset in PIMAGE_DOS_HEADER->e_lfanew. This is start of PIMAGE_NT_HEADERS
fileStream.Read(buffer, 0, 4);
fileStream.Seek(BitConverter.ToUInt32(buffer, 0), SeekOrigin.Begin);
// Validate PE\0\0 header.
fileStream.Read(buffer, 0, 4);
if (BitConverter.ToUInt32(buffer, 0) != PeHeaderValue)
{
throw new TestRunnerException(string.Format(CultureInfo.InvariantCulture, "The specified assembly '{0}' does not appear to be valid.", path));
}
// Read the PIMAGE_FILE_HEADER->Machine value.
fileStream.Read(buffer, 0, 2);
return (MachineType)BitConverter.ToUInt16(buffer, 0);
}
}
/// <summary>
/// Safely loads the assembly.
/// </summary>
/// <param name="path">The path to the assembly to load.</param>
/// <returns>The loaded assembly</returns>
public static Assembly SafeLoadAssembly(string path)
{
try
{
return Assembly.Load(path);
}
catch (ArgumentNullException)
{
}
catch (FileNotFoundException)
{
}
catch (FileLoadException)
{
}
catch (BadImageFormatException)
{
}
return null;
}
}
}
答案 2 :(得分:0)
尝试使用 imageload
加载dllhttp://msdn.microsoft.com/en-us/library/ms680209(v=vs.85).aspx
当然,如果此函数失败,请将其卸载或获取上一个错误,以便您可以研究输出并在此之后决定此dll是否与您的c#应用程序相同。