Determine if app is WinForms or WebForms

2019-06-18 23:16发布

问题:

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.

回答1:

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.



回答2:

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



回答3:

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.



回答4:

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


回答5:

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.



回答6:

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);
    }
}


回答7:

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.