如何确定DLL是否是一个托管程序集或本机(prevent加载本地的dll)? [英] How to determine whether a DLL is a managed assembly or native (prevent loading a native dll)?

查看:161
本文介绍了如何确定DLL是否是一个托管程序集或本机(prevent加载本地的dll)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

背景:

我的C#应用​​程序包括一个插件框架和通用的插件加载器。

My C# application includes a plugin framework and generic plugin loader.

插件加载枚举应用程序目录,以确定插件的DLL(本质上,它在这个时候搜索* .DLL)。

The plugin loader enumerates the application directory in order to identify plugin dlls (essentially it searches for *.dll at this time).

在同一个应用程序目录是土生土长(在Windows,non-.net)DLL,其中,间接,插件dll的一个依靠。

Within the same application directory is a native (Windows, non-.net) dll, which, indirectly, one of the plugin dlls depends upon.

插件加载盲目地假定native.dll是一个.NET程序集DLL,仅仅是因为它只是检查文件扩展名。当它尝试加载机DLL,抛出一个异常:

The plugin loader blindly assumes that the native.dll is a .NET Assembly dll, simply because it only checks the file extension. When it attempts to load the native dll, an exception is thrown:

无法加载文件或程序集native.dll或它的一个依赖项。该模块应包含清单的程序集。

"Could not load file or assembly 'native.dll' or one of its dependencies. The module was expected to contain an assembly manifest."

我基本上是创建诊断报告,如果插件加载失败,所以我想,以避免该日志充满了消息有关无法加载机DLL(我甚至不想尝试)。

I basically create a diagnostic report if plugin loading fails, so I'm trying to avoid having this log filled up with messages about not being able to load the native dll (which I don't even want to attempt).

的问题:

有没有办法,我可以用它来确定文件是否恰好是一个.NET程序集,让我不要试图在所有加载机DLL一些.NET API调用?

Is there some .NET API call that I can use to determine whether a binary happens to be a .NET assembly so that I don't attempt to load the native dll at all?

也许长期来看,我将我的插件移动到一个子目录,但现在,我只想周围的工作,不涉及硬编码native.dll的名字我的插件加载器里。

Perhaps longer term I will move my plugins to a subdirectory, but for now, I just want a work around that doesn't involve hard-coding the "native.dll" name inside my plugin loader.

我想我在寻找某种静态Assembly.IsManaged()API调用的,我已经忽略了.... presumably没有这样的API的存在?

I guess I'm looking for some kind of static Assembly.IsManaged() API call that I've overlooked.... presumably no such API exists?

推荐答案

如何判断文件是否是一个.NET程序集或不?

public static bool IsManagedAssembly(string fileName)
{
    uint peHeader;
    uint peHeaderSignature;
    ushort machine;
    ushort sections;
    uint timestamp;
    uint pSymbolTable;
    uint noOfSymbol;
    ushort optionalHeaderSize;
    ushort characteristics;
    ushort dataDictionaryStart;
    uint[] dataDictionaryRVA = new uint[16];
    uint[] dataDictionarySize = new uint[16];

    Stream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);
    BinaryReader reader = new BinaryReader(fs);

    //PE Header starts @ 0x3C (60). Its a 4 byte header.
    fs.Position = 0x3C;
    peHeader = reader.ReadUInt32();

    //Moving to PE Header start location...
    fs.Position = peHeader;
    peHeaderSignature = reader.ReadUInt32();

    //We can also show all these value, but we will be       
    //limiting to the CLI header test.
    machine = reader.ReadUInt16();
    sections = reader.ReadUInt16();
    timestamp = reader.ReadUInt32();
    pSymbolTable = reader.ReadUInt32();
    noOfSymbol = reader.ReadUInt32();
    optionalHeaderSize = reader.ReadUInt16();
    characteristics = reader.ReadUInt16();

    // Now we are at the end of the PE Header and from here, the PE Optional Headers starts... To go directly to the datadictionary, we'll increase the stream’s current position to with 96 (0x60). 96 because, 28 for Standard fields 68 for NT-specific fields From here DataDictionary starts...and its of total 128 bytes. DataDictionay has 16 directories in total, doing simple maths 128/16 = 8. So each directory is of 8 bytes. In this 8 bytes, 4 bytes is of RVA and 4 bytes of Size. btw, the 15th directory consist of CLR header! if its 0, its not a CLR file :)
    dataDictionaryStart = Convert.ToUInt16(Convert.ToUInt16(fs.Position) + 0x60);
    fs.Position = dataDictionaryStart;
    for (int i = 0; i < 15; i++)
    {
        dataDictionaryRVA[i] = reader.ReadUInt32();
        dataDictionarySize[i] = reader.ReadUInt32();
    }
    fs.Close();

    if (dataDictionaryRVA[14] == 0) return false;
    else return true;
}

这篇关于如何确定DLL是否是一个托管程序集或本机(prevent加载本地的dll)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆