6

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.
Community
  • 1
  • 1
dummy
  • 255
  • 1
  • 3
  • 7

7 Answers7

5

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
  • 17,669
  • 6
  • 70
  • 85
4

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

Anton Gogolev
  • 113,561
  • 39
  • 200
  • 288
  • Thanks! Could you also check my updated question for an additional detail? – dummy Jun 02 '10 at 10:46
  • As M. Smith has written below, HttpContext.Current is null when doing async stuff, so it doesn't always work. – dummy Jun 02 '10 at 15:26
2

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.

Community
  • 1
  • 1
Martin Smith
  • 438,706
  • 87
  • 741
  • 845
2

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
  • 722
  • 3
  • 7
1

The AppDomain holds information of the associated config file. Since web apps have their config file named "web.config" and all others have "{app}.exe.config" this determines the type of application.

/// <summary>
/// Extensions for the AppDomain class
/// </summary>
public static partial class AppDomainExtensions
{
    /// <summary>
    /// Determines whether the specified app domain is a web app.
    /// </summary>
    /// <param name="appDomain">The app domain.</param>
    /// <returns>
    ///     <c>true</c> if the specified app domain is a web app; otherwise, 
    /// <c>false</c>.
    /// </returns>
    public static bool IsWebApp(this AppDomain appDomain)
    {
        var configFile = (string)appDomain.GetData("APP_CONFIG_FILE");
        if (string.IsNullOrEmpty(configFile)) return false;
        return (
          Path.GetFileNameWithoutExtension(configFile) ?? string.Empty
          ).Equals(
            "WEB", 
            StringComparison.OrdinalIgnoreCase);
    }
}
Daniel Fisher lennybacon
  • 3,865
  • 1
  • 30
  • 38
1

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
  • 722
  • 3
  • 7
  • 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 Jun 02 '10 at 10:55
  • 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 Jun 02 '10 at 11:17
  • 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 Jun 02 '10 at 12:17
0

You have a convinient way to do it with framework property:

HostingEnvironment.IsHosted

Reference System.Web and add System.Web.Hosting namespace.

When IsHosted is true it means the host is web.

jruizaranguren
  • 12,679
  • 7
  • 55
  • 73