一种从中央存储库加载DLL的方法

Kar*_*lee 9 c c++ windows dll

我们有很多产品,每个产品的应用程序都有一些常见的DLL.现在我们将每个常见的DLL复制到每个产品的bin目录中,并将它们视为私有程序集.这不必要地增加了每个产品的msi大小,当DLL中出现问题时,我们必须构建包含DLL的每个产品的msi并进行部署.

反正是指示产品应用程序使用公共私有目录来加载DLL [使用manifest scheme ..]?[注意:将私有目录添加到PATH env将不会提供解决方案,就好像SYSTEM目录中存在具有相同名称的DLL一样,这将获取对我们的私人目录的特权]

-Kartlee

Chr*_*cke 8

您没有指定您的环境是.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)应用程序配置文件现在要做的支持探测元素应用程序配置文件

这意味着您应该能够提供一个路径(相对于您的应用程序)到包含您要加载的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>
Run Code Online (Sandbox Code Playgroud)

现在,创建一个名为\ Program Files\AcmeCommon的文件夹,在其中创建一个文件夹acme.thedll,并将thedll.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>
Run Code Online (Sandbox Code Playgroud)

现在我们在一个公共位置使用公共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='*'\"")
Run Code Online (Sandbox Code Playgroud)

如果您使用的是较旧的构建环境,其中清单是手工制作的,则需要将以下xml与App1文件夹中的app1.exe.manifest合并:

<dependency>
  <dependentassembly>
    <assemblyIdentity type="win32" name="acme.thedll" version="1.2.3.4"   processorArchitecture="x86" language="*"/>
  </dependentassembly>
</dependency>
Run Code Online (Sandbox Code Playgroud)

这应关闭圆圈:当应用程序加载时,win32加载程序将加载应用程序清单(app1.exe.manifest或作为RT_MANIFEST资源嵌入)并了解"acme.thedll"程序集.它还将加载应用程序配置文件(app1.exe.config)并了解搜索程序集的专用路径.然后它将加载并将"acme.thedll.manifest"添加到应用程序"激活上下文".然后,当加载程序尝试加载"thedll.dll"时,它将搜索激活上下文数据库,在acme.thedll程序集中找到它,并从程序集位置加载它.


Rub*_*ias 1

如果您谈论的是 .NET,您可以:

  • 使用以下命令直接从数据库加载 DLLAssembly.Load(byte[])
  • 通过使用Assembly.TypeResolve事件
  • 通过使用TypeProvider
  • 通过在配置文件中定义探针目录

喜欢:

<configuration>   
    <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
            <probing privatePath="bin"/>
        </assemblyBinding>
    </runtime>
</configuration>
Run Code Online (Sandbox Code Playgroud)