从中央存储库加载DLL的一种方法 [英] A way to load DLL from central repository

查看:86
本文介绍了从中央存储库加载DLL的一种方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有很多的产品,并有在每个产品的应用程序的一些常见的DLL。现在,我们每个拷贝共同的DLL到每个产品的bin目录,并把它们当作私人集会。这不必要地增加每个产品的MSI大小,当在DLL中出现问题,我们必须建立每个产品的MSI包括DLL和部署。

We have lot of products and there are some common DLLs across each product's application. Right now we copy each common DLL into each product's bin directory and treat them as private assembly. This unnecessarily increase the msi size of each product and when a problem occurs in a DLL we have to build each product's msi comprising the DLL and deploy it.

反正是有指导产品的应用程序使用用于加载DLL一个共同的私有目录[使用清单方案..]
[注:添加私有目录PATH环境不会提供一个解决方案,如果不存在具有相同名称的DLL在SYSTEM目录中存在,这将需要特权在我们的私有目录]

Is there anyway to instruct the product application to use a common private directory to be used for loading DLLs [ using manifest scheme.. ]? [ Note: Adding the private directory to PATH env will not provide a solution as if there is a DLL with same name exist in SYSTEM directory, that would take the privilege over our private directory ]

-Kartlee

推荐答案

如果您的环境是.NET或直的Win32不指定。

You don't specify if your environment is .NET or straight Win32.

我假设它的Win32,因为如果它的.NET的技术来做到这一点都非常接近交出的东西,如全局程序集缓存条款。

I am assuming its Win32 because if its .NET the technologies to do this are all much closer to hand in terms of things like the Global Assembly Cache.

在的Win32方面就有可能以两种方式之一从共享位置装载dll:

In terms of Win32 it is possible to load Dlls from a shared location in one of two ways:


  • 使用调用LoadLibrary与明确的完整路径。这意味着你不能使用静态链接 - 在所有产品中使用的所有的DLL函数都将通过GetProcAddress的进行访问。不能导入从通过调用LoadLibrary加载的DLL的C ++类 - 它们必须静态链接到工作,所以这种方法可能会或可能不会是可行的。它不是非常难写伪装成dll的接口Shim头文件,并根据需要为每个呼叫做只是在时间DLL加载和GetProcAddress。

  • Use LoadLibrary with explicit full paths. This means you cannot use static linking - all dll functions used in all products will have to be accessed via GetProcAddress. You cannot import c++ classes from dll's loaded via LoadLibrary - they must be statically linked to work so this approach may or may not be viable. Its not terribly hard to write shim header files that masquerade as the dll's interface and do a just in time dll load and GetProcAddress as needed for each call.

另外一种选择是把DLL的进入所谓的并行程序集方,并将其安装到WinSxS文件存储。不要被大牌害怕。 并排组件侧是指一个DLL文件以及清单文件与版本信息。
然后,每个不同的应用程序会把强名称 - 其中包括版本信息 - 到其应用程序清单每个DLL,它使用,和Win32 DLL的加载程序将使用这个从WinSxS文件店挑共同的DLL的正确实例。其基本过程是在MSDN文章指南描述了创建边并排组件

The other option is to turn the dll's into what are called "side by side assemblies" and install them into the WinSxS store. Don't be scared by the big name. "side by side assembly" means "A Dll file plus manifest file with version information". Each of the various applications would then put 'strong name' - which includes version information - into its application manifest for each dll it uses, and the Win32 Dll loader will use this to pick the correct instance of the common dll from the WinSxS store. The basic process is described in the MSDN article Guidelines for Creating Side-by-side Assemblies

在Windows版本6.1及以上(Windows Server 2008和讽刺了名为Windows 7)应用程序配置文件现在做支持的Application配置文件

On Windows versions 6.1 and up (Windows Server 2008 and the ironically named Windows 7) application configuration files DO NOW support the probing element in Application Configuration Files

这意味着你应该能够提供(相对于您的应用程序),以包含包含要加载DLL组件文件夹的路径。

This means you should be able to provide a path (relative to your application) to a folder containing containing dll assemblies you want to load.

好吧,我已经做了Windows 7的一些测试,而这个作品:

Ok, Ive done some testing on Windows 7, and this works:

假设你安装在\\ Program Files文件\\ App1的应用程序app1.exe,这取决于一些常见的DLLthedll.dll

Assuming you have an application app1.exe installed in \Program Files\App1, that depends on some common dll "thedll.dll"

在应用程序文件夹(\\ Program Files文件\\程序App1)创建一个文件App1.exe.config,并给它包含以下内容: -

In the application folder (\Program Files\App1) create a file App1.exe.config and give it the following contents :-

<configuration>   
   <windows>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
        <probing privatePath="..\AcmeCommon"/>
    </assemblyBinding>
  </windows>
</configuration>

现在,创建一个名为\\ Program Files文件\\ AcmeCommon文件夹,并在它的文件夹acme.thedll和thedll.dll复制到\\​​ Program Files文件\\ AcmeCommon \\ acme.thedll

Now, create a folder called \Program Files\AcmeCommon, and in it a folder acme.thedll, and copy thedll.dll into \Program Files\AcmeCommon\acme.thedll

此外,创建AcmeCommon \\ acme.thedll一个名为acme.thedll.manifest - 这将是描述被称为acme.thedll

Also create a file in AcmeCommon\acme.thedll called acme.thedll.manifest - this will be the assembly manifest describing the assembly called 'acme.thedll'

acme.thedll.manifest的内容将是: -

The contents of acme.thedll.manifest will be:-

<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。

Now we have the common dll, in a common location, as a native sxs assembly. We have the app, with a config file that will, on Windows 7 and 2008 server (and up) tell it to search for assemblies in the common location. But the app is still trying to link to the dll as a dll, rather than via an assembly.

要获得应用程序加载程序集,我们需要一个清单文件添加到应用程序。如果您在使用Visual Studio,您的应用程序可能已经配置为创建和嵌入通过连接器和工具清单项目设置体现。在这种情况下,最简单的方法,告诉应用程序有关的组件添加以下code到至少一个头或C / CPP文件中的项目后重建它: -

To get the app to load the assembly, we need to add a manifest file to the application. If you are using visual studio, your applications are probably already configured to create and embed manifests via the linker and manifest tool project settings. In which case the easiest way to tell the app about the assembly is to rebuild it after adding the following code to at least one header or c/cpp file in the project :-

#pragma comment(linker,"/manifestdependency:\"type='win32' name='acme.thedll' version='1.2.3.4' processorArchitecture='x86' language='*'\"")

如果您使用的是旧版本的环境,舱单是手工制作的,你需要在该文件夹App1的合并app1.exe.manifest以下XML:

If you are using an older build environment where the manifests are hand made you would need to merge the following xml with app1.exe.manifest in the App1 folder:

<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,它将查询的激活上下文分贝,发现其在acme.thedll组件,以及从装配位置加载。

This should close the circle: When the app loads the win32 loader will load the application manifest (app1.exe.manifest or embedded as a RT_MANIFEST resource) and learn about the "acme.thedll" assembly. It will also load the application config file (app1.exe.config) and learn about the private path to search for assemblies. And it will then load and add "acme.thedll.manifest" to the apps "activation context". Then, when the loader tries to load "thedll.dll" it will search the activation context db, find that its in the acme.thedll assembly, and load it from the assemblies location.

这篇关于从中央存储库加载DLL的一种方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆