如何在应用程序启动时执行汇编代码
我知道这个问题与之前的几个问题类似,但我找不到确切的答案。我有一个应用程序框架,除其他外,它可以处理未处理的错误。目前,我要求主机应用程序在应用程序的 Main
方法中调用 Register
方法来注册处理程序和各种子系统。我真的很想摆脱这种依赖关系,并用一些程序集级属性替换 Register
方法的参数。因此,我需要一种方法来检测主机应用程序是否已从我的程序集中启动 - 就好像它是 .NET 框架的一部分一样。
我想避免来自主机应用程序内的任何显式调用,或配置文件中的任何特殊行(尽管这些更容易接受)。因此,只需添加对程序集的引用就会导致在应用程序启动时初始化这些功能。有没有人想出办法来实现这一点?
为了清楚起见,这里是我理想的前后场景的示例:
// BEFORE:
[System.STAThread]
private static int Main(string[] args)
{
SupportLibrary.Register(typeof(Program).Assembly, SupportLibrary.ApplicationType.WinForms);
// Get the application initialised...
}
// AFTER:
[System.STAThread]
[SupportLibrary.ApplicationType(SupportLibrary.ApplicationType.WinForms)]
private static int Main(string[] args)
{
// Get the application initialised...
}
重点是我想摆脱注册支持库的显式调用,而是在应用程序启动和支持程序集时隐式注册它们负载。
I know this question is similar to several previous ones, but I can't find an exact answer. I have an application framework that, amongst other things, handles unhandled errors. At the moment I require that the host application calls a Register
method in the application's Main
method to register the handlers and various sub-systems. I'd really like to get rid of this dependency and replace the Register
method's parameters with some assembly-level attributes. So, what I need is a way of detecting that the host application has started from within my assembly - as if it were part of the .NET framework.
I'd like to avoid any explicit calls from within the host app, or any special lines in the configuration file (although these are more acceptable). So just adding a reference to the assembly causes the features to be initialised when the application starts. Has anyone worked out a way of making this happen?
To make things clear, here is an example of my ideal before and after scenarios:
// BEFORE:
[System.STAThread]
private static int Main(string[] args)
{
SupportLibrary.Register(typeof(Program).Assembly, SupportLibrary.ApplicationType.WinForms);
// Get the application initialised...
}
// AFTER:
[System.STAThread]
[SupportLibrary.ApplicationType(SupportLibrary.ApplicationType.WinForms)]
private static int Main(string[] args)
{
// Get the application initialised...
}
The point being that I would like to get rid of the explicit call to register the support libraries and instead have them implicit registered when the application starts and the support assembly loads.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
所以,我找到了答案。这可能并不适用于所有情况,但它对我有用,因为我的库的使用方式意味着它总是在应用程序启动时加载。
CLR 规范规定了要定义的模块初始值设定项。这些在第一次访问模块(例如程序集)时和执行任何代码之前被调用 - 这正是我想要的。在 C# 中没有直接指定这些内容,但本文:
http://tech.einaregilsson.com/2009/12/16/module-initializers-in-csharp
提供了编译后将 IL 直接注入程序集所需的工具(这对我有用,因为我不签署或混淆我的代码)。我希望这对某人有帮助。
So, I've found the answer. This may not be applicable in every case, but it works for me because the way in which my library is used means that it is always loaded when the application starts.
The CLR specification provides for Module Initializers to be defined. These are called the first time a module (e.g. an assembly) is accessed and before any code is executed - which is exactly what I want. There is no direct provision for specifying these in C#, but this article:
http://tech.einaregilsson.com/2009/12/16/module-initializers-in-csharp
provides the tools necessary for injecting the IL directly into your assembly after compiling (which works for me because I am not signing or obsfuscating my code). I hope that helps someone.
最简单的方法是使用配置文件 - 只需添加自定义部分,您将在其中编写需要初始化的所有程序集。您的主机应用程序将遍历该列表并对您需要的每个程序集调用
Assembly.Load()
方法。之后,您可以执行任何必要的初始化(使用自定义属性标记要在程序集中调用的方法等)。我不确定是否有一种方法(我认为是)可以立即加载所有应用程序的程序集。如果您能找到这样的方法,那么您可以标记需要使用 suctom 属性初始化的所有程序集,然后只需遍历所有已加载的程序集 (
AppDomain.CurrentDomain.GetAssemblies()
) 来过滤具有您的属性的程序集。The easiest way to do this is a way with config file - just add custom section where you will write all assemblies needed to be initialized. Than your host app will go throught that list and call
Assembly.Load()
method on each of the assemblies you need. After that you can perform any necessary initialization (marking methods to be called in the assemblies with custom attributes, etc).I'm not sure if there is a way (I think it is) to load all application's assemblies at once. If you can find such way than you can mark all assemblies needed to be initialized with suctom attribute and then just go through all loaded assemblies loaded (
AppDomain.CurrentDomain.GetAssemblies()
) to filter ones with your attribute.