问题描述
我们有一个依赖于许多第三方DLL组的应用程序。不幸的是,这些第三方DLL的作者都没有非常一致地命名它们,因此很难看到哪个DLL是哪个组的一部分。
We have an application that depends on a number of groups of third-party DLLs. Unfortunately, none of the writers of these third-party DLLs have named them very consistently so it is hard to see which DLL is part of what group.
尝试并管理为此,我们希望将第三方DLL组放置在应用程序文件夹中的文件夹中,而不是在应用程序旁边放置类似的内容。
To try and manage this, we would like to put groups of third-party DLLs in a folder in our application folder rather than along-side the application something like this.
--> Application Folder
--> Application.exe
--> MyDLL1.dll
--> MyDLL2.dll
--> Third Party 1 DLL folder
--> Third Party 1 DLL 1.dll
--> Third Party 1 DLL 2.dll
--> Third Party 1 DLL 3.dll
--> Third Party 2 DLL folder
--> Third Party 2 DLL 1.dll
--> Third Party 2 DLL 2.dll
--> Third Party 2 DLL 3.dll
我的问题是如何获取动态链接程序以查找并加载
My question is how to get the dynamic linker to find them and load them?
我们可以使用LoadLibrary()和GetProcAddress()手动完成此操作,但这非常繁琐。看来我们可以使用清单和探测来做到这一点,但这似乎仅适用于Windows 7(我们需要在XP及更高版本上工作)。
We could do this manually with LoadLibrary() and GetProcAddress(), however this is intensely tedious. It looks like we might be able to do this with manifests and "probing", but this seems to be Windows 7 only (we need to work on XP and above).
更新
我们最终使用清单来完成此操作(感谢@Chris)-我们还不得不跳过其他几个方面万一有人在寻找解决方案!
We used manifests to do this in the end (thanks @Chris) - there were a couple of other hoops we had to jump through in case anyone is looking for a solution!
首先,我们的程序集实际上有几个DLL,一个我们链接到的DLL,然后再链接到另一个。所有这些DLL都需要在其清单中添加程序集相关性(您可以使用mt.exe来执行此操作,而无需访问这些DLL的源代码)。
First, our "assembly" actually has several DLLs, one that we link to that then links to others. All of these DLLs will need the assembly dependency adding to their manifests (you can use mt.exe to do this without having access to the the source code of these DLLs).
第二,程序集需要与DLL一起使用,而不是与EXE一起使用-我们的DLL实际上是一个已经在应用程序子文件夹中的插件。
Second, the assembly needs to go alongside the DLL, not alongside the EXE - our DLL was actually a plugin that was already in a subfolder of the app.
这是我们的最终布局:
--> Application Folder
--> Application.exe
--> Plugins folder
--> MyDLL1.dll
--> Third Party 1
--> Third Party 1.manifest
--> A.dll
--> B.dll
--> C.dll
如果MyDLL1.dll是链接到A.dll和A.dll的插件然后链接到B.dll和C.dll:
If MyDLL1.dll is a plugin that links to A.dll, and A.dll links to both B.dll and C.dll then:
- 第三方1.manifest需要包含所有A.dll,B .dll和C.dll作为程序集
- MyDLL1.dll需要在其清单中存在对第三方1的依赖项,否则动态链接程序将找不到A.dll
- A.dll需要在其清单中添加对第三方1的依赖项,否则动态链接程序将找不到B.dll和C.dll
- 第三方1文件夹需要与 MyDLL1.dll并排,而不是 Application.exe并排。
- "Third Party 1.manifest" needs to include all A.dll, B.dll and C.dll as an assembly
- "MyDLL1.dll" needs a dependency entry in its manifest to "Third Party 1" or the dynamic linker won't find A.dll
- A.dll needs a dependency entry in its manifest to "Third Party 1" or the dynamic linker won't find B.dll and C.dll
- The "Third Party 1" folder needs to go alongside "MyDLL1.dll", not alongside "Application.exe"
我,(3)有点烦人。您可能认为链接器会在程序集中查找相关的DLL。
For me, (3) is a bit irritating. You would think that the linker would look in the assembly for dependent DLLs.
推荐答案
您可以对清单进行探测,而无需进行探测。
创建假程序集-通过定义包含dll的.manifests。 (为此,dll中没有要求进行任何更改。)
自从程序集支持添加到NT 5.1(Windows XP)之后,Windows加载程序首先通过扫描具有程序集名称的文件夹来查找程序集。
You can do it with manifests without probing.Create "fake" assemblies - by defining .manifests, that contain the dlls. (No change is requried in the dll's for this)Since assembly support was added to NT 5.1 (Windows XP) the windows loader first looks for assemblies by scanning for a folder with the assemblies name.
例如,如果您需要使用应用程序分发Visual C 2008的Microsoft Visual C运行时,则可以创建一个如下所示的文件夹结构:
So, for example, if you need to distribute the Microsoft Visual C runtime for Visual C 2008 with your application, you could create a folder structure that looks like this:
--> Application Folder
--> Application.exe
--> MyDll1.dll
--> MyDll2.dll
--> Microsoft.VC90.CRT
--> Microsoft.VC90.CRT.manifest
--> msvcr90.dll
--> msvcp90.dll
--> msvcm90.dll
此方案适用于您的第三方dll。
然后,您需要做的就是将假程序集作为从属程序集添加到应用程序的清单中(如果您的dll有清单,(并且它们访问了第三方dll),那么它们的清单将必须具有
This same scheme would work for your 3rd party dlls.All you would then need to do would be to add the "fake" assemblies as dependent assemblies to your application's manifest (if your dlls have manifests, (and they access the 3rd party dlls) then their manifests will have to have entries too.
描述程序集的清单文件需要一个assemblyIdentity,以及每个dll的文件节点:
The manifest files describing the assemblies need an assemblyIdentity, and a file node per dll:
<assembly manifestVersion="1.0">
<assemblyIdentity type="Win32" name="Assembly Name" version="1.0.0.0" processorArchitecture="x86" />
<file name="dll1.dll" />
<file name="dll2.dll" />
</assembly>
并且您的应用程序和dll是使用MS Visual Studio 2005或更高版本构建的,以下编译指示将使您的应用程序寻找程序集中的dll:
And your application, and dlls are built with MS Visual Studio 2005 or later, the following pragma directive would make your app look for the dlls in the assemblies:
#pragma comment(linker, "/manifestDependency:\"name='Assembly Name' processorArchitecture='*' version='1.0.0.0' type='win32' \"")
这篇关于如何将第三方Windows DLL组织到应用程序文件夹中的子文件夹中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!