我不想试图找出我正在处理的个别问题,而是想给出 10,000 英尺高度的概述。我一边学习 .NET,一边怀疑我明显遗漏了一些东西。
我周日正在加班,如果有人愿意捐出五美分,我将非常感激。
如下:
我们的支柱产品是过程控制系统。
有许多可能的方法来扩展/定制系统。传统上,我们将控制系统发布与受控过程工厂的特定配置分开,以便两者可以单独维护。
C:\Control System 基础版本\(我称之为CS$)这是基础版本。 Bug 修复等。
C:\Delivery Project\(我称之为Proj$) 这是受控系统的信息。
一点背景知识:
- 我们的服务工程师希望能够重新安装或升级 CS$ 文件夹,而不会丢失自定义数据。
- Delivery 项目传统上由 XCOPY 部署。
- 两者之间存在一些 dll 引用,这在 MFC 中运行良好。
- 在我们的实验室机器上,同时安装多个版本是很常见的。
- 该系统从驻留在交付项目中的 .bat 文件启动,该文件设置环境然后启动。启动过程环境变量很大。
现在,我在使用 .NET 时遇到了一些适应此模型的困难。
当系统使用嵌入式.NET控件或显示winform时,会按需加载mscorlib,并以CS$\Run\bin作为应用程序基本路径。这给我带来了一些问题:
- 在 Proj$ 下部署的 .NET 程序集位于应用程序基本路径之外。
- 如果人们重新安装控制系统基础,部署在CS$\Run\bin下的.NET程序集将被删除。当然,我可以将部署作为批量启动的一部分。
- .NET 程序集路径由 Proj$ 文件夹结构中的文本配置提供。交付项目中的相对路径很常见,但当他们开始访问 CS$ 时就会出现问题,CS$ 可能会发生变化。
- 部署在 CS$\Run\bin 下的 .NET 程序集可能具有进一步的依赖项。我可能在 CS$\run\bin\ext1 和 CS$\run\bin\ 下有两个不同版本的 Util1.dll 。由于探测路径顺序,这会导致 CLR 无法解析 CS$\run\bin\ext1\util1.dll。
- 我尝试过分离应用程序域,但在 CS$\run\bin\ext1\ext1.dll 中找到的类实例可能有数百个。我大量使用单例(静态)来协调资源管理。
不用说,我大量使用Reflector和Fuslogvw。还有其他我应该了解的工具吗?
是否可以检查运行进程中的 CLR 信息?由于 mscorlib 是按需加载的,因此我有时发现 CLR 的应用程序基础相差甚远。这有时会阻止加载我的代码,因此我无法以编程方式访问应用程序域或将其输出以进行跟踪。
在从应用程序基本路径开始之前,有什么方法可以控制探测路径从调用程序集开始相对?
GAC 中的混合模式程序集可以访问 CS$ 中的 MFC 资源吗?
虽然我不拥有按需加载mscorlib的MFC代码库,但我确实有一句话在里面。从那里可以做些什么吗?我将请求在加载 mscorlib 时输出关键信息以进行跟踪(以及异常)。
对于我似乎缺少的某些方面的文章、工具或简短描述将不胜感激。
我感谢您花时间阅读本文并在我在这里描述的遗留痛苦中保持清醒的头脑:)
Rather than trying to piece out the individual pains I'm dealing with, I want to give the 10 000 feet overview of it. I learn .NET as I go, and I suspect that there is something obvious that I'm missing here.
I'm sitting working overtime on a Sunday and I'd really appreciate if someone would toss in their five cents.
Here goes:
Our mainstay product is a process control system.
There are many possible ways of extending/customizing the system. We have traditionally separated the control system release from the specific configuration of the Process Plant being controlled so that the two can be maintained seperately.
C:\Control System base release\ (I call this CS$) This is the base release. Bug fixes etc.
C:\Delivery Project\ (I call this Proj$) This is the information of the system being controlled.
A little background:
- Our service engineers expects to be able to reinstall or upgrade the CS$ folder without loss of customization data.
- The Delivery project is traditionally deployed by XCOPY.
- There is some dll-referencing between the two, which works fine in the MFC.
- On our lab machines, it is common to have many versions installed simultaneously.
- The system is launched from .bat-files residing in the delivery project that sets up the environment and then launches. The launching process is environment-variable intense.
Now, I experience some difficulties in accommodating this model when using .NET.
When the system is using embedded .NET controls or displays a winform, the mscorlib is loaded on demand with CS$\Run\bin being the app base path. This presents me with some problems:
- .NET assemblies deployed under Proj$ are outside the app base path.
- .NET assemblies deployed under CS$\Run\bin will be deleted if people reinstall the control system base. I can make deployment part of the batch startup, of course.
- .NET assemblies paths are provided by textual configuration residing in the Proj$ folder structure. Relative paths within the delivery project is common, but is a problem when they start accessing CS$, which is subject to change.
- .NET assemblies deployed under CS$\Run\bin may have further dependencies. I may have two different versions of Util1.dll under CS$\run\bin\ext1 and CS$\run\bin\ . This results in CLR not being able to resolve CS$\run\bin\ext1\util1.dll because of the probing path order.
- I have experimented with seperating appdomains, but instances of classes found in CS$\run\bin\ext1\ext1.dll can number in the hundreds. And I make heavy use of Singletons (static) to coordinate resource management.
Needless to say, I use a lot of Reflector and Fuslogvw. Are there any more tools that I should know of?
Is it possible to inspect running processes for the CLR information within them? Since the mscorlib is loaded on demand, I sometimes find that CLR has a app base that is way off. This sometimes prevents my code from being loaded, so I can't access the appdomain programatically or output it to trace.
Is there any way to control the probing path to start relative from the calling assembly before starting from the app base path?
Can mixed mode assemblies in the GAC access MFC resources in CS$?
Although I don't own the MFC code base that loads the mscorlib on demand, I do have a saying in it. Is there something that can be done from there? I am going to request that key information when loading mscorlib is output to trace (as well as exceptions).
Articles, tools or a short description of some aspect I appear to be missing would be appreciated.
I appreciate you taking the time to read this and to maintain a clear head throughout this legacy pain I'm describing here :)
发布评论
评论(2)
如果 .Net 的程序集探测逻辑不适合您,您始终可以使用 IHostAssemblyManager 和 IHostAssemblyStore 用您自己的代码扩展 CLR 主机。请参阅此博文或阅读这本书了解有关该选项的更多信息。
另一种选择是重构应用程序以适应 .Net 的规则,而不是强迫 .Net 遵循您的规则。也许如果您写下功能需求而不是技术需求,您可能会发现可以通过另一种方式使用 .Net 达到相同的目标。就像使用程序集版本作为程序集标识的一部分一样,卷影副本,发布商政策等。
If .Net's assembly probing logic is not working out for you, you can always extend the CLR host with your own code using IHostAssemblyManager and IHostAssemblyStore. See this blog post or read this book to learn more about that option.
Another option would be to refactor the application to fit .Net's rules instead of forcing .Net to play by your rules. Maybe if you write down the functional demands instead of the technical you might find you can reach the same goals with .Net in another way. Like using the assembly version as part of an assembly's identity, shadow copy, publisher policies, etc.
如果您记录了如何解决非托管程序集的此问题,将会很有帮助。引导 Windows 查找非托管 DLL 的选项受到更多限制。如果您将 .NET 程序集安装到 GAC,那么您的问题很容易解决,但这与您的部署策略不太兼容。
无论如何,您几乎肯定可以通过实现 AppDomain.AssemblyResolve 事件来解决您的问题。当 CLR 需要查找程序集但自己无法找到它时,它会调用此函数。您的代码必须知道 CS$ 和 Proj$ 文件夹的位置才能正常工作。
It would have been helpful if you had documented how you solved this problem for your unmanaged assemblies. Options to direct Windows to find an unmanaged DLL are a lot more restricted. Your issue would be simple to solve if you'd install the .NET assemblies to the GAC but that's not very compatible with your deployment strategy.
Anyhoo, you can almost surely solve your problem by implementing the AppDomain.AssemblyResolve event. The CLR will call this when it needs to find an assembly but can't find it by itself. Your code would have to be aware of the locations of the CS$ and Proj$ folders to make this work right.