views:

431

answers:

5

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?

+2  A: 

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.

Fredrik Mörk
Its a support library providing infrastructure for other libraries and applications that can be used in a variety of contexts. The idea is that this library provides a common means of handling unhandled errors and reporting them to the host application.
open-collar
In all cases an email is sent with details to a Jira server. But in Windows a screenshot is captured and the user is shown a dialogue. In console apps details are written to the console. I have mentioned error handling here, but there may well be other purposes too.
open-collar
I updated my answer in response to your comment
Fredrik Mörk
+5  A: 

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.?

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.

For example in a Web Application you would utilize:

WebErrorLogger error = new WebErrorLogger();
RSolberg
Or: error = new GUIErrorLogger(); / error = new WebErrorLogger(); / error = new ConsoleErrorLogger(); where they all implement the interface ErrorLogger.
Samir Talwar
That'd work too...
RSolberg
This is where I am at the moment - but I am trying to remove the need for the consumer to initialise in this way. If no-one can come up with a better idea then I might well have to stick with this.
open-collar
+3  A: 

This sounds like something that would be best handled with configuration. Perhaps injection of something like an IExceptionHandler interface via an IOC.

Steve Willcock
+3  A: 

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

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.

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)

JoshBerke
+1  A: 
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.

Services in windows usually have 'services.exe' as their parent, the way of determining the parent process is well described over at CodeProject.

ASP.NET process runs under special user called ASPNET, user's name can be obtained from an access token .

arul
This is closest to what I am trying to achieve. This link seems to provide a reasonable amount of information about whether or not a binary is a console app.: http://www.codeguru.com/cpp/w-p/system/misc/article.php/c2897. I can't rely on the ASPNET user being used - we run using all kind of service accounts for various purposes. I think in conjunction with Josh's answer below I can probably come up with a reasonable stab at an answer.
open-collar