views:

154

answers:

5

Is there a way to determine if running app is WinForms or Web at runtime?

[Edit]

Is there actually a problem if I reference both System.Web and System.Windows.Forms in my class library?

[Summary] (so far)

What I've learned so far:

  • HttpContext.Current is null if checked in an async thread, so it cannot reliably be used in a helper method. HttpRuntime.Cache doesn't really help since I am not looking for the cached context at all (or am I missing something here?).
  • on the other hand, System.Reflection.Assembly.GetEntryAssembly() seems to return null in web apps, and non null in WinForms. Should that be taken for granted? There should be more "hacks" like this, so which one to use?
  • referencing both System.Web and System.Windows.Forms in a helper library should be fine, according to this thread.
+2  A: 

Check whether HttpContext.Current is null. If it is, it's not a webapp.

Anton Gogolev
Thanks! Could you also check my updated question for an additional detail?
dummy
As M. Smith has written below, HttpContext.Current is null when doing async stuff, so it doesn't always work.
dummy
+1  A: 

HttpContext.Current can be null in a Web Application if it is doing asynchronous processing. From this thread HttpRuntime.Cache might be a better thing to test.

Martin Smith
+1  A: 

For this question to make sense, you would have to have included references to both System.Web and System.Windows in your project. This in itself is (in my opinion) a bit of a code smell.

You are likely better off collecting the needed info in the calling method (which should be firmly in either the Web or WinForms domain) and passing this to whatever metods need this info as an argument.

[edit]

One way of doing this shown below. Still ugly, but it means only having to set the fact that you are in a webApp once.

public class Helper 
{ 
   public static bool IsCurrentAppWeb; //defaults to false
   public bool TheActualHelpFullFunction()
   {
       if(Helper.IsCurrentAppWeb)
       {
           //do web specific things
       }
       else
       {
           //do things the non-web way.
           //note that this does not tell you 
           //if you are currently running a WinForm or service or...
       }
   }
}
LaustN
Well, the point is to have common logic in a shared assembly (which would reference whatever it needs to reference), so calling assemblies will only need to reference that shared assembly.
dummy
No offense, but the code you posted is a school example of a code smell, and a much worse way to do it than to add two references. Classes should never expose public fields for other clients to change. If you need to pass some information to the method, pass it as a parameter (like `bool TheActualHelpFunction(bool isCurrentAppWeb)`), don't expect from your callers to change a bunch of flags before calling a method.
dummy
I agree, my example isn't better. The thing I would like to avoid, is having an assembly change its behavior depending on the environment it is running in.This would not be an issue for you, but it might become an issue for the next person to inherit the code. He might not know that the behavior changes depending on running context.Reading your other question (http://stackoverflow.com/questions/2957042/get-the-file-path-of-the-current-app) makes the intention much clearer to me. I can only applaud the intention.
LaustN
+1  A: 

Another way of doing this, is to look at the current process name.

using System.Diagnostics;

public class Helper
{
  public static bool IsCurrentAppWeb()
  {
    return Process.GetCurrentProcess().ProcessName == "aspnet_wp"; 
  }
}

This solution works for XP, the string to compare to varies by environment. When running VS in default debug mode, you will need to compare agains the name of the integrated testing server.

Not the prettiest solution, but it does allow you to omit references to either web or winforms assemblies.

Have a look at http://msdn.microsoft.com/en-us/library/system.diagnostics.process_members(v=VS.100).aspx for more details on the Process class.

LaustN
+3  A: 

In your edit you specify that your helper class is in a seperate assembly. If you want to avoid references and you have control over your app.config files you could put an

<add key="typeOfSystem" value="Forms|Web"/>

in your projects and access it with

ConfigurationManager.AppSettings["typeOfSystem"]

using ConfigurationManager along with its property AppSettings. Don't forget to add a reference to System.Configuration in your project. Note that you get the AppSettings of the hosting application. By doing this you need to add a key in your parent application's app.config, or output some error or warning if it's not specified perhaps.

Patrick