【问题标题】:Scanning DLLs for .NET assemblies with a particular interface - some DLLs throw R6034!使用特定接口扫描 .NET 程序集的 DLL - 一些 DLL 会抛出 R6034!
【发布时间】:2011-02-17 21:41:29
【问题描述】:

我有一个程序需要在其主机上发现插件 DLL。

它通过枚举(相当大的)路径中的所有 DLL 来做到这一点。这条路径包含很多东西,包括原生 DLL。

foreach (var f in Directory.EnumerateFiles(@"c:\Program Files", "*.dll", SearchOption.AllDirectories))
{
    try
    {
        var assembly = Assembly.LoadFile(f);
        var types = assembly.GetTypes();
        foreach (var type in types)
        {
            if (type.GetInterface("My.IInterface") != null)
            {
                plugins.Add(f);
                break;
            }
        }
        assembly = null;
    }
    catch (Exception e)
    {
    }
}

如果我的扫描程序遇到 MS 运行时 DLL(例如 msvcm80.dll),我会收到无法捕获的运行时错误 R6034:“应用程序尝试错误地加载 C 运行时库。”此窗口阻止程序的执行。我不想要这个 DLL(显然);有什么方法可以从这种情况中得到一个优雅的错误吗?

[相关问题:如果该 DLL 当前未加载到进程空间中,是否有一种有效的(例如非异常)方法来确定 DLL 是否为 .NET 程序集?]

【问题讨论】:

    标签: c# .net reflection assemblies


    【解决方案1】:

    首先使用Assembly.ReflectionOnlyLoadFrom 进行仅反射加载。只有在程序集中找到插件后,才能使用Assembly.LoadFrom 完全加载它。

    要回答您的其他问题,您可以检查文件是否具有 CLR 标头。

    See this post "Read CLR Header" on m.p.dotnet.framework

    这些应该可以让您在搜索插件时避免任何异常和错误消息框。

    【讨论】:

    • 对 ReflectionOnlyLoadFrom 很感兴趣。太糟糕了,它具有仅将给定名称的一个程序集加载到 appdomain 中的相同限制。使用备用应用域显然非常痛苦;我找不到任何人成功地描述了如何获取另一个应用程序域,成功加载程序集(没有指定特定类型),然后询问这些程序集的属性。哎呀。
    【解决方案2】:

    在 \Program Files 上似乎不是一个好主意...有人可以将恶意 DLL 放在那里吗?

    您是否考虑过使用MEF?它也可能更安全一些。

    有一个 DirectoryCatalog 会为您自动加载程序集并返回您的接口数组。

    不确定您是否熟悉依赖注入或 (IoC) 控制反转,但您也可以使用 MEF。

    它包含在 .Net 4.0 中。

    【讨论】:

    • 好吧,这太荒谬了。 MEF 表现出同样的问题。如果您告诉 MEF 在包含 VC++ 运行时库的目录上使用 DirectoryCatalog,您会得到相同的 R6034 弹出窗口。 (另外,DirectoryCatalog 不支持目录递归,所以无论如何你都必须枚举所有你想要的目录。)我喜欢 MEF 抽象,但不幸的是它并没有解决问题。
    • 你知道吗; 1) MEF 从给定目录加载所有程序集,然后过滤给定类型或 2) 它调用 Assembly.ReflectionOnlyLoad 方法,过滤然后加载?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多