动态加载DLL

9
我有一个需要使用大量插件的程序。
每个插件都必须支持一个非常基本的接口,这个接口在一个DLL中定义(为了简化问题,我们称之为IBaseComponent)。
每个插件将位于特定目录(AppDirectory\plugin\plugin-type)。每个插件的插件dll可以具有任何名称 (AppDirectory\plugin\plugin-type\plugin-name.dll)。
因此,我需要检查每个插件子目录,找到每个支持IBaseComponent接口的类的插件,并实例化该类并调用一些插件函数。
好的,所有的事情都很好,但问题是我似乎遇到了一些奇怪的问题。
每个插件都需要在单独的插件文件夹中拥有Base.dll文件(而不仅仅是在将加载插件的程序中),并且似乎在动态加载具有需要被加载的dll的dll时,我会得到许多错误和警告。
我正在使用:
pluginModule = System.Reflection.Assembly.ReflectionOnlyLoadFrom(PathToAssembly);

为了获取插件dll并使用:
types = moduleAssembly.GetTypes();

为了获取dll中包含的类型,我正在遍历这些类型,并检查单个类型是否实现了IBaseComponent接口(表示这是一个有效的可加载类),代码如下:
if (type.GetInterface("FrameworkNameSpace.IBaseComponent") != null)
    //it's of the IBaseComponent interface

后来,为了从dll中创建类的实例,我使用以下代码:

pluginModule = System.Reflection.Assembly.LoadFrom(PathToAssembly);

然后使用:
types = component.GetTypes();

为了获取模块中的类型,然后选择并加载与上述接口相同的支持接口的类。
问题似乎出现在我使用以下内容时:
types = component.GetTypes();

当实际尝试加载类时,而不是简单地查看它。(因此我使用了不同的LoadFromReflectionOnlyLoad)

在调用GetTypes时(第二个插件,但从未出现在第一个插件中!)收到的异常是:

{"Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information."}

使用LoaderExceptions属性如下:

{"The specified module could not be found. (Exception from HRESULT: 0x8007007E)":null}

我不确定为什么会出现这种情况。DLL文件在插件文件夹中,包含IBaseComponent接口的DLL文件也在每个插件目录中。我做错了吗?
此外,是否需要在每个插件子目录中保留一个包含IBaseComponent的DLL副本以及程序本身使用的DLL副本?或者我做错了什么,可以允许我删除此要求?
我知道MEF是我想要使用的东西,但不幸的是,因为我需要在.net 2.0上支持它,所以无法使用MEF。

1
你能否启用融合日志并查看是否存在融合/程序集加载问题(fuslogvw.exe)? - rene
1个回答

5
这是一个LoadLibrary()失败。听起来你的插件依赖于一些非托管的DLL。是的,Windows很难找到这些DLL,因为它没有理由在插件目录中查找。也许第一次可以工作是因为你的应用程序的默认目录恰好设置为正确的目录。那么解决方法也会是使用Environment.CurrentDirectory。
准确找出哪些依赖项无法找到是关键。非托管的依赖项不会在fuslogvw.exe中显示,您可以从SysInternals的ProcMon实用程序的跟踪中找到它。

好的,我会调整这些东西并看看我能找到什么。那是一个很好的方向去探索。如果我弄清楚了,我会告诉你的。感谢您的帮助。 - Script and Compile
将Environment.CurrentDirectory更改为当前插件目录并没有解决问题。我认为这可能是IBaseComponent DLL尝试被第二个插件加载时出现的问题。似乎第一个插件可以正确找到所有内容并且运行正常,而第二个插件在尝试加载时会出现错误并崩溃。可能存在DLL冲突?不确定发生了什么。仍在查看ProcMon的内容。等我知道更多后会回复您。再次感谢。 - Script and Compile
似乎有一个文件'MSRVC71.dll'存在问题,这看起来是一个微软Visual C dll文件?这让我相信这可能是由我的dll加载的dll引起的问题(反过来又加载了这个dll,唉)。随着我进一步了解,我会进行更新,我可能在追逐一个无用之兔。我们拭目以待。 - Script and Compile
是的,这正是我所说的DLL类型。它的真实名称是msvcr71.dll,它是用于非托管C或C++代码的支持库。将其复制到c:\windows\system32以缺乏更好的位置。 - Hans Passant
1
太好了!运作得很好。不太确定为什么我没有那个dll,即使重新安装了2.0 net sdk 我还是没有它。算了。关于“动态dll加载时找不到dll文件”的基本答案是“获取Procman,查找异常未提及的dll依赖项”。 - Script and Compile

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接