从中央存储库加载DLL的一种方法
我们有很多产品,每个产品的应用程序中都有一些常见的DLL。 现在我们将每个常见的DLL复制到每个产品的bin目录中,并将它们视为私有程序集。 这不必要地增加了每个产品的msi大小,并且当DLL发生问题时,我们必须构建包含DLL的每个产品的msi并部署它。
无论如何要指示产品应用程序使用通用专用目录来加载DLL [使用清单方案..]? [注意:将私有目录添加到PATH env将不会提供解决方案,就好像在SYSTEM目录中存在具有相同名称的DLL一样,这会在我们的专用目录中拥有特权]
-Kartlee
你不指定你的环境是.NET还是直线Win32。
我假设它的Win32是因为如果它的.NET这样做的技术在全局程序集缓存等方面都非常接近。
就Win32而言,可以通过以下两种方式之一从共享位置加载Dll:
使用带有显式完整路径的LoadLibrary。 这意味着您不能使用静态链接 - 所有产品中使用的所有dll函数都必须通过GetProcAddress访问。 你不能从通过LoadLibrary加载的DLL导入c ++类 - 它们必须静态链接才能工作,所以这种方法可能或不可行。 编写可以伪装成dll接口的shim头文件并且在每次调用时都会根据需要及时执行dll加载和GetProcAddress,这并不难。
另一种选择是将dll转换成所谓的“并排程序集”,并将它们安装到WinSxS存储中。 不要被这个大名字吓倒。 “并排装配”是指“一个Dll文件和带有版本信息的清单文件”。 然后,每个应用程序都会将“强名称”(包括版本信息)放入其应用程序清单中,以便使用它的每个dll,并且Win32 Dll加载程序将使用它从WinSxS存储区中选择正确的常用dll实例。 基本过程在MSDN文章创建并行程序集指南中进行了描述
在Windows 6.1及更高版本(Windows Server 2008和具有讽刺意味的Windows 7)应用程序配置文件中,DO Now支持应用程序配置文件中的探测元素
这意味着你应该能够提供一个路径(相对于你的应用程序)到一个包含你想要加载的dll程序集的文件夹。
好吧,我已经在Windows 7上做了一些测试,并且这可以工作:
假设您在 Program Files App1中安装了应用程序app1.exe,这取决于一些常见的dll“thedll.dll”
在应用程序文件夹( Program Files App1)中创建一个文件App1.exe.config并为其提供以下内容: -
<configuration>
<windows>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="..AcmeCommon"/>
</assemblyBinding>
</windows>
</configuration>
现在,创建一个名为 Program Files AcmeCommon的文件夹,并在其中创建一个文件夹acme.thedll,并将该dll.dll复制到 Program Files AcmeCommon acme.thedll
在AcmeCommon acme.thedll中创建一个名为acme.thedll.manifest的文件 - 这将是描述名为“acme.thedll”的程序集的程序集清单
acme.thedll.manifest的内容将为: -
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity name="acme.thedll" version="1.2.3.4" processorArchitecture="x86" type="win32"/>
<file name="thedll.dll"/>
</assembly>
现在我们有一个共同的DLL,在一个共同的位置,作为本地的sxs程序集。 我们有应用程序,配置文件将在Windows 7和2008服务器(及以上)中告诉它在常用位置搜索程序集。 但该应用程序仍然试图链接到DLL作为DLL,而不是通过组装。
为了让应用程序加载程序集,我们需要将清单文件添加到应用程序中。 如果您使用的是Visual Studio,那么您的应用程序可能已经配置为通过链接器和清单工具项目设置来创建和嵌入清单。 在这种情况下,告诉应用程序有关程序集的最简单方法是在将以下代码添加到项目中的至少一个头文件或c / cpp文件后重建它: -
#pragma comment(linker,"/manifestdependency:"type='win32' name='acme.thedll' version='1.2.3.4' processorArchitecture='x86' language='*'"")
如果您使用的是手动制作清单的较旧版本环境,则需要将以下xml与App1文件夹中的app1.exe.manifest合并:
<dependency>
<dependentassembly>
<assemblyidentity type="win32" name="acme.thedll" version="1.2.3.4" processorArchitecture="x86" language="*"/>
</dependentassembly>
</dependency>
这应该关闭该圈:当应用程序加载时,win32加载器将加载应用程序清单(app1.exe.manifest或作为RT_MANIFEST资源嵌入)并了解“acme.thedll”程序集。 它还将加载应用程序配置文件(app1.exe.config)并了解搜索程序集的私有路径。 然后它会加载并添加“acme.thedll.manifest”到应用程序“激活上下文”。 然后,当加载器尝试加载“thedll.dll”时,它将搜索激活上下文db,在acme.thedll程序集中找到它,并从程序集位置加载它。
如果你在谈论.NET,你可以:
Assembly.Load(byte[])
直接从数据库加载DLL Assembly.TypeResolve
事件 TypeProvider
类 喜欢:
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="bin"/>
</assemblyBinding>
</runtime>
</configuration>
我在跟随克里斯的回答。 确保清单和配置中的案例正确。 否则他们会失败。 我能够获得程序集加载,但不会选择DLL。 在我的情况下,系统32中的Windows DLL被选中,而不是我自己的同名。 在Dependency Walker中,我的DLL被加载,但在运行时,使用Process Explorer,Windows的副本被加载。 有任何想法吗?
链接地址: http://www.djcxy.com/p/44493.html