你不是在要求一些非常基本的东西。Windows 根本不支持你想要的。
您有一些选项可以解决此问题:
- 创建两个 DLL。您的插件实现 dll,静态链接到您需要的任何其他 dll。还有一个由托管应用程序加载的简单“外观”dll。外观 dll 调用 SetDllDirectory 然后 LoadLibrary 以使用所需的搜索路径加载您的实现 dll,然后,对于每个插件导出的函数,它实现一个存根函数,该函数使用 GetProcAddress 将调用直接传递给您的实现 dll。
如果插件接口复杂,而你使用的dll接口不复杂,那么:
我们想要这样做的原因是通过 SxS 技术链接的 dll 的搜索顺序与常规 dll 搜索顺序不同:- 即 - 在搜索 c:\windows\WinSxS 后,windows 将搜索与引用dll的dll,而不是exe的文件夹。
首先清点您的插件 dll 需要链接到的所有卫星 dll,并从中创建一个“程序集”。这意味着:创建一个带有一堆 file= 节点的 .manifest 文件。您需要为程序集命名。让我们称之为“MyAssembly”。
在您的 dll 文件夹中创建文件“MyAssembly.manifest”,其内容类似于以下内容:(列出您需要包含的每个 dll)
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity name="MyAssembly" processorArchitecture="*" type="win32" version="1.0.0.1"/>
<file name="firstrequireddll.dll"/>
<file name="2ndrequireddll.dll"/>
</assembly>
现在,这就是你的程序集清单。我们已经完成了一半。
下半部分是实际让您的 dll 使用程序集,为此您需要将清单资源添加到您的 Dll 文件中。该清单最终需要包含以下内容:-
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="MyAssembly" version="1.0.0.1" processorArchitecture="*"/>
</dependentAssembly>
</dependency>
</assembly>
显然,应用程序清单(嵌入 dll 时是一个令人困惑的名称)也允许使用<file>
节点,因此可能可以跳过创建程序集,而直接使用
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<file name="firstrequireddll.dll"/>
<file name="2ndrequireddll.dll"/>
</assembly>
作为 dll 的清单。我还没有玩弄那个迭代,所以我不确定它如何改变正常的 dll 搜索路径(如果有的话)。
在不了解您的开发环境的情况下,很难知道如何建议您如何将清单添加到 dll。如果您正在编辑 .rc 文件并手动输入清单,请知道在 Dlls 中要使用的资源 id 是 2,而不是 exe 示例中通常使用的 1。
如果您使用的是 DevStudio 2005 或更高版本,则有一个方便的#pragma 指令,它将神奇地使所有内容都具有正确的 ID 并位于正确的位置。
如果项目设置为默认值,VS2005 及更高版本将自动生成并根据需要嵌入清单。此#pragma 将向生成的清单添加额外的程序集依赖项:-
#if _MSC_VER >= 1400 // VS2005 added this directive
#pragma comment(linker, \
"\"/manifestdependency:type='Win32' "\
"name='Company.Product.Subsystem' "\
"version='6.0.0.0' "\
"processorArchitecture='*' "\
"language='*'\"")
#endif