使用 XCOPY 部署动态加载程序集及其依赖项

发布于 2024-08-06 14:27:41 字数 568 浏览 2 评论 0原文

我有一个动态加载应用程序的应用程序加载器。 应用程序是一个程序集,其所有依赖项都位于一个文件夹中。 使用 XCOPY 部署,我可以通过复制/删除文件夹来添加/删除应用程序。 为了促进标准 .NET 程序集绑定,我将应用程序文件夹复制到加载程序的 bin 下。 我在配置文件中设置了探测 privatePath,一切都非常顺利。

应用程序使用框架,即共享程序集作为依赖项。

现在我有一个要求,规定每个应用程序都必须能够使用自己的框架版本。

当我在 GAC 中安装框架版本时,这非常有效,并且不同版本的程序集都可以很好地加载到默认的 AppDomain 中。

现在我想返回到我的 XCOPY 解决方案并将正确的框架版本复制到相应的应用程序文件夹中,但解决方案崩溃了。

第一个应用程序引用其框架工作正常,第二个应用程序抱怨找不到程序集且清单不匹配。

就好像 .NET 加载程序在程序集与“privatePath”中的文件夹第一次匹配后停止探测,并且不再进一步查找。

关于如何实现与使用 GAC 时相同的行为有什么想法吗? 我还可以在配置、代码库中指定什么吗? (请不要绝对文件路径)。

克尔, 米歇尔

I have an application loader that dynamically loads applications.
An application is an assembly with all of its dependents in a single folder.
Using XCOPY deployment I can add/remove applications by copying/deleting a folder.
To facilitate standard .NET assembly binding I copy the application folders under the bin of the loader.
I set the probing privatePath in the config file and everything works like a charm.

The applications uses a framework, i.e. shared assemblies as dependents.

Now I have a requirement that states that each application has to be able to use its own version of the framework.

This works perfectly when I install the framework versions in the GAC, and the different versions of the assembly are loaded into the default AppDomain just fine.

Now I want to get back to my XCOPY solution and copy the correct framework versions in their corresponding application folders and the solution breaks.

The first application referencing its framework works fine, the second complains about not finding the assembly and the manifests not matching.

It's as if the .NET loader stops probing after a first match of the assembly with a folder in "privatePath" and does not look any further.

Any ideas on how to have the same behavior as when using the GAC?
Anything else I could specify in config, codeBase? (no absolute file paths please).

kr,
Michel

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

十年不长 2024-08-13 14:27:41

根据这篇关于程序集的文章

您还应该记住 CLR
按预定顺序查看
探测期间的目录数。给定一个
MyAssemblies 的 privatePath 值,
CLR 现在将探测程序集
在下面命名为 MyLibrary
订单:

C:/Apps/MyLibrary.DLL
C:/Apps/MyLibrary/MyLibrary.DLL
C:/Apps/MyAssemblies/MyLibrary.DLL
C:/Apps/MyAssemblies/MyLibrary/MyLibrary.DLL
C:/Apps/MyLibrary.EXE
C:/Apps/MyLibrary/MyLibrary.EXE
C:/Apps/MyAssemblies/MyLibrary.EXE
C:/Apps/MyAssemblies/MyLibrary/MyLibrary.EXE

文件路径的顺序
程序集文件的 CLR 探针是
重要的是因为探测过程
一旦 CLR 找到程序集就停止
具有正确文件名的文件。如果
您部署一个应用程序
MyLibrary.dll 的一个版本
ApplicationBase 目录和第二个
子目录中的版本
MyAssemblies,哪个 DLL 文件将
CLR 负载?您应该看到 CLR
将会加载 DLL 到
ApplicationBase 目录,因为
始终是搜索的第一个目录
在探测过程中由 CLR 执行。

更新:

查看这篇文章。它或多或少地解决您遇到的相同问题。

According to this article on Assemblies:

You should also remember that the CLR
looks through a predetermined sequence
of directories during probing. Given a
privatePath value of MyAssemblies, the
CLR will now probe for an assembly
named MyLibrary in the following
order:

C:/Apps/MyLibrary.DLL
C:/Apps/MyLibrary/MyLibrary.DLL
C:/Apps/MyAssemblies/MyLibrary.DLL
C:/Apps/MyAssemblies/MyLibrary/MyLibrary.DLL
C:/Apps/MyLibrary.EXE
C:/Apps/MyLibrary/MyLibrary.EXE
C:/Apps/MyAssemblies/MyLibrary.EXE
C:/Apps/MyAssemblies/MyLibrary/MyLibrary.EXE

The sequence of file paths in which
the CLR probes for an assembly file is
important because the probing process
stops once the CLR locates an assembly
file with the correct file name
. If
you deploy an application along with
one version of MyLibrary.dll in the
ApplicationBase directory and a second
version in the subdirectory
MyAssemblies, which DLL file will the
CLR load? You should see that the CLR
is going to load the DLL in the
ApplicationBase directory because that
is always the first directory searched
by the CLR during the probing process.

Update:

Check this post. It deals with more or less the same problem you're having.

表情可笑 2024-08-13 14:27:41

如果您使用 Assembly.LoadFrom 加载在这些文件夹中找到的所有程序集,您会更幸运。

这会改变探测行为,并允许运行时在本地搜索程序集最初加载的位置,以便找到其引用。不过,您将在程序集级别获得框架版本共享。

即:

  • 应用程序“a”加载,导致框架 v1.02 加载。
  • 应用程序“b”加载,导致框架 v1.01 加载。
  • 应用程序“c”加载,链接到框架 v1.02,并简单地重用加载应用程序“a”后加载的代码。

也就是说,如果您没有显式加载程序集,则此解决方案可能没有用。

在这种情况下 - 我会采用 Yannick M. 提到的答案中的解决方案 - 挂钩到 AssemblyResolve 事件;当您开始加载应用程序时存储一些静态状态,以便您的事件处理程序知道正在加载哪个应用程序;如果任何程序集无法解析,您可以查看此状态以确定它应该在哪里查找并从那里加载程序集。

You will have more luck if you use Assembly.LoadFrom to load all the assemblies you find in these folders.

This changes probing behaviour and allows the runtime to search locally to where the assembly was originally loaded from in order to find its references. You will get framework-version sharing at the assembly level, though.

That is:

  • App 'a' loads, causing Framework v1.02 to load.
  • App 'b' loads, causing Framework v1.01 to load.
  • App 'c' loads, linked to Framework v1.02, and simply reuses the code that was loaded after App 'a' was loaded.

that said - this solution might be of no use if you're not explicitly loading the assemblies.

In that case - I'd go with the solution in the answer mentioned by Yannick M. - hook into the AssemblyResolve event; store some static state as you begin to load an app so your event handler knows which app is loading; and if any Assembly fails to resolve, you can look at this state to determine where it should be looking and load the assembly from there.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文