I have a library that needs to respond to exceptions in different ways depending on whether it is running in a Console app, WinForms, AspNet or Windows Service. I have experimented with looking at various properties in the System.Windows.Forms and System.Web namespaces, but I can't find a reliable way of detecting exactly which kind of application is hosting my library. Has anyone been here before? Does anyone have a reliable solution?
我有一个库需要以不同的方式响应异常,具体取决于它是在控制台应用程序,WinForms,AspNet还是Windows服务中运行。我已经尝试过查看System.Windows.Forms和System.Web命名空间中的各种属性,但是我找不到一种可靠的方法来检测哪种应用程序正在托管我的库。有没有人来过这里?有没有人有可靠的解决方案?
5 个解决方案
#1
I'd question your design before going down this route but I thought this was an interesting challenge and wanted to see if I could find anyways.
在走这条路线之前我会问你的设计,但我认为这是一个有趣的挑战,想看看我是否能找到它。
ASP.Net : Check HttpContext.Current is not null. You could also look at System.Web.Hosting.ApplicationManager.GetApplicationManager(), but I'm not sure how this will behave outside of Asp.net
ASP.Net:检查HttpContext.Current不为null。您还可以查看System.Web.Hosting.ApplicationManager.GetApplicationManager(),但我不确定这将如何在Asp.net之外运行
Window Forms: You could try and use System.Windows.Forms.Application.OpenForms, this will return any open forms. An assumption is being made that a windows form application would never not have any forms. Also a console application can also start a win form.
窗体形式:您可以尝试使用System.Windows.Forms.Application.OpenForms,这将返回任何打开的窗体。正在假设Windows表单应用程序永远不会有任何形式。控制台应用程序也可以启动win表单。
Service: Not sure on this but I'm wondering if you can check the name of the process. There must also be a windows API since the task manager shows when a process is a service (At least on Vista it does)
服务:对此不确定,但我想知道您是否可以检查流程的名称。还必须有一个Windows API,因为任务管理器显示进程何时是一项服务(至少在Vista上它是这样)
#2
If I understand what you are seeking correctly, you have a single library that does error handling, but you want the library to know if the source is web, console, winforms, etc.?
如果我理解你正在寻找什么,你有一个单独的库进行错误处理,但是你想让库知道源是web,console,winforms等吗?
You might be able to utilize a property in the library, say an enumeration, that tracks what the consuming applications type is. For example...
您可以使用库中的属性(例如枚举)来跟踪消费应用程序类型的内容。例如...
ErrorLogger error = new ErrorLogger(ErrorLoggerAppType.WinForm);
ErrorLogger error = new ErrorLogger(ErrorLoggerAppType.Web);
ErrorLogger error = new ErrorLogger(ErrorLoggerAppType.Console);
EDIT
From Samir in comments...
In addition you could always just have a class for each type of application implement the same interface within your error logger library.
编辑来自Samir的评论...此外,您可以随时为每种类型的应用程序创建一个类,在您的错误记录器库中实现相同的接口。
For example in a Web Application you would utilize:
例如,在Web应用程序中,您将使用:
WebErrorLogger error = new WebErrorLogger();
#3
This sounds like something that would be best handled with configuration. Perhaps injection of something like an IExceptionHandler interface via an IOC.
这听起来像配置最好处理的东西。也许通过IOC注入类似IExceptionHandler接口的东西。
#4
This feels like you would want to look into the design a bit more, is my spontaneous though. A class library should not need to know things like that about its caller.
这感觉就像你想要更多地看一下设计,虽然是我自发的。类库不需要知道关于其调用者的事情。
What is it that you want to change in the exception handling behaviour based on the context in which it is running?
您希望在基于运行它的上下文的异常处理行为中更改什么?
Based on your comment, I would suggest looking into defining an interface for an error handler, and then create the needed number of implementations of that interface (one for WinForms, one for Console and so on), and have the client application create and inject the corresponting implementation into the library. That way you lift the knowledge-need out from the library and shift the responsibility over to the client application. These implementations can still reside inside your class library, but the decision of which to use will be for the client application to make.
根据您的评论,我建议查找定义错误处理程序的接口,然后创建该接口的所需数量的实现(一个用于WinForms,一个用于控制台等等),并让客户端应用程序创建和注入相应的实施到图书馆。这样,您就可以从库中解除知识需求,并将责任转移到客户端应用程序。这些实现仍然可以驻留在类库中,但是决定使用哪个将由客户端应用程序进行。
#5
BOOL IsConsole(PBYTE file)
{
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)file;
if(pDosHeader->e_magic == IMAGE_DOS_SIGNATURE)
{
PIMAGE_NT_HEADERS pImageHeaders = (PIMAGE_NT_HEADERS)(file + pDosHeader->e_lfanew);
if(pImageHeaders->Signature == IMAGE_NT_SIGNATURE)
{
IMAGE_OPTIONAL_HEADER optionalHeader = pImageHeaders->OptionalHeader;
return (optionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI);
}
}
return FALSE;
}
IMAGE_SUBSYSTEM_WINDOWS_CUI
can be excahnged with IMAGE_SUBSYSTEM_WINDOWS_GUI
to detect whether it's a GUI application instead of console.
可以使用IMAGE_SUBSYSTEM_WINDOWS_GUI来移除IMAGE_SUBSYSTEM_WINDOWS_CUI,以检测它是否是GUI应用程序而不是控制台。
Services in windows usually have 'services.exe
' as their parent, the way of determining the parent process is well described over at CodeProject.
Windows中的服务通常将'services.exe'作为其父级,在CodeProject中可以很好地描述确定父进程的方法。
ASP.NET process runs under special user called ASPNET, user's name can be obtained from an access token .
ASP.NET进程在名为ASPNET的特殊用户下运行,可以从访问令牌获取用户名。
#1
I'd question your design before going down this route but I thought this was an interesting challenge and wanted to see if I could find anyways.
在走这条路线之前我会问你的设计,但我认为这是一个有趣的挑战,想看看我是否能找到它。
ASP.Net : Check HttpContext.Current is not null. You could also look at System.Web.Hosting.ApplicationManager.GetApplicationManager(), but I'm not sure how this will behave outside of Asp.net
ASP.Net:检查HttpContext.Current不为null。您还可以查看System.Web.Hosting.ApplicationManager.GetApplicationManager(),但我不确定这将如何在Asp.net之外运行
Window Forms: You could try and use System.Windows.Forms.Application.OpenForms, this will return any open forms. An assumption is being made that a windows form application would never not have any forms. Also a console application can also start a win form.
窗体形式:您可以尝试使用System.Windows.Forms.Application.OpenForms,这将返回任何打开的窗体。正在假设Windows表单应用程序永远不会有任何形式。控制台应用程序也可以启动win表单。
Service: Not sure on this but I'm wondering if you can check the name of the process. There must also be a windows API since the task manager shows when a process is a service (At least on Vista it does)
服务:对此不确定,但我想知道您是否可以检查流程的名称。还必须有一个Windows API,因为任务管理器显示进程何时是一项服务(至少在Vista上它是这样)
#2
If I understand what you are seeking correctly, you have a single library that does error handling, but you want the library to know if the source is web, console, winforms, etc.?
如果我理解你正在寻找什么,你有一个单独的库进行错误处理,但是你想让库知道源是web,console,winforms等吗?
You might be able to utilize a property in the library, say an enumeration, that tracks what the consuming applications type is. For example...
您可以使用库中的属性(例如枚举)来跟踪消费应用程序类型的内容。例如...
ErrorLogger error = new ErrorLogger(ErrorLoggerAppType.WinForm);
ErrorLogger error = new ErrorLogger(ErrorLoggerAppType.Web);
ErrorLogger error = new ErrorLogger(ErrorLoggerAppType.Console);
EDIT
From Samir in comments...
In addition you could always just have a class for each type of application implement the same interface within your error logger library.
编辑来自Samir的评论...此外,您可以随时为每种类型的应用程序创建一个类,在您的错误记录器库中实现相同的接口。
For example in a Web Application you would utilize:
例如,在Web应用程序中,您将使用:
WebErrorLogger error = new WebErrorLogger();
#3
This sounds like something that would be best handled with configuration. Perhaps injection of something like an IExceptionHandler interface via an IOC.
这听起来像配置最好处理的东西。也许通过IOC注入类似IExceptionHandler接口的东西。
#4
This feels like you would want to look into the design a bit more, is my spontaneous though. A class library should not need to know things like that about its caller.
这感觉就像你想要更多地看一下设计,虽然是我自发的。类库不需要知道关于其调用者的事情。
What is it that you want to change in the exception handling behaviour based on the context in which it is running?
您希望在基于运行它的上下文的异常处理行为中更改什么?
Based on your comment, I would suggest looking into defining an interface for an error handler, and then create the needed number of implementations of that interface (one for WinForms, one for Console and so on), and have the client application create and inject the corresponting implementation into the library. That way you lift the knowledge-need out from the library and shift the responsibility over to the client application. These implementations can still reside inside your class library, but the decision of which to use will be for the client application to make.
根据您的评论,我建议查找定义错误处理程序的接口,然后创建该接口的所需数量的实现(一个用于WinForms,一个用于控制台等等),并让客户端应用程序创建和注入相应的实施到图书馆。这样,您就可以从库中解除知识需求,并将责任转移到客户端应用程序。这些实现仍然可以驻留在类库中,但是决定使用哪个将由客户端应用程序进行。
#5
BOOL IsConsole(PBYTE file)
{
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)file;
if(pDosHeader->e_magic == IMAGE_DOS_SIGNATURE)
{
PIMAGE_NT_HEADERS pImageHeaders = (PIMAGE_NT_HEADERS)(file + pDosHeader->e_lfanew);
if(pImageHeaders->Signature == IMAGE_NT_SIGNATURE)
{
IMAGE_OPTIONAL_HEADER optionalHeader = pImageHeaders->OptionalHeader;
return (optionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI);
}
}
return FALSE;
}
IMAGE_SUBSYSTEM_WINDOWS_CUI
can be excahnged with IMAGE_SUBSYSTEM_WINDOWS_GUI
to detect whether it's a GUI application instead of console.
可以使用IMAGE_SUBSYSTEM_WINDOWS_GUI来移除IMAGE_SUBSYSTEM_WINDOWS_CUI,以检测它是否是GUI应用程序而不是控制台。
Services in windows usually have 'services.exe
' as their parent, the way of determining the parent process is well described over at CodeProject.
Windows中的服务通常将'services.exe'作为其父级,在CodeProject中可以很好地描述确定父进程的方法。
ASP.NET process runs under special user called ASPNET, user's name can be obtained from an access token .
ASP.NET进程在名为ASPNET的特殊用户下运行,可以从访问令牌获取用户名。