确定应用程序是WinForms还是WebForms

6

有没有办法在运行时确定应用程序是WinForms还是Web?

[编辑]

如果在我的类库中同时引用System.WebSystem.Windows.Forms,是否会出现问题?

[总结](到目前为止)

到目前为止我了解到:

  • 如果在异步线程中检查,HttpContext.Current将为null,因此不能可靠地在帮助方法中使用。HttpRuntime.Cache并不能真正帮助我,因为我根本不需要缓存上下文(或者我错过了什么?)。
  • 另一方面,System.Reflection.Assembly.GetEntryAssembly()似乎在Web应用程序中返回null,而在WinForms中返回非空值。这应该被视为理所当然吗?应该有更多像这样的“hack”,那么应该使用哪一个?
  • 根据this thread,在帮助库中同时引用System.WebSystem.Windows.Forms应该没有问题。
7个回答

5
在您的编辑中,您指定了您的辅助类位于一个单独的程序集中。如果您想避免引用并且您可以控制您的app.config文件,您可以放置一个。
<add key="typeOfSystem" value="Forms|Web"/>

在你的项目中访问它,并使用HTML标记


ConfigurationManager.AppSettings["typeOfSystem"]

使用ConfigurationManager和它的属性AppSettings。不要忘记在项目中添加对System.Configuration的引用。请注意,您可以获取托管应用程序的AppSettings。这样做,您需要在父应用程序的app.config中添加一个键,否则可能会输出一些错误或警告。


4
检查HttpContext.Current是否为null。如果是,则不是Web应用程序。

谢谢!您能否再检查一下我更新的问题,看看有没有额外的细节? - dummy
正如M. Smith所述,当进行异步操作时,HttpContext.Current可能为null,因此它并不总是可用。 - dummy

2

另一种做法是查看当前进程的名称。

using System.Diagnostics;

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

这个解决方案适用于XP,但要比较的字符串随环境而异。在使用默认调试模式运行VS时,您需要将其与集成测试服务器的名称进行比较。

虽然不是最美观的解决方案,但它确实允许您省略对Web或Winforms程序集的引用。

有关进程类的更多详细信息,请参阅http://msdn.microsoft.com/en-us/library/system.diagnostics.process_members(v=VS.100).aspx


2

HttpContext.Current在Web应用程序中如果进行异步处理可能为空。从这个线程中可以看出,HttpRuntime.Cache可能是更好的测试对象。


1

为了让这个问题有意义,您必须在项目中包含对System.Web和System.Windows的引用。这本身就是(在我看来)有点代码异味。

您最好在调用方法中收集所需信息(应该牢固地属于Web或WinForms领域),并将其作为参数传递给需要此信息的任何方法。

[编辑]

下面展示了一种方法。仍然很丑陋,但它意味着只需要设置您在WebApp中的事实一次。

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

其实重点是在一个共享程序集中拥有通用逻辑(该程序集将引用它需要引用的任何内容),因此调用程序集只需要引用该共享程序集即可。 - dummy
不要误会,但你发布的代码是一个代码异味的典型例子,比添加两个引用更糟糕。类永远不应该公开字段以供其他客户端更改。如果需要将一些信息传递给方法,请将其作为参数传递(例如 bool TheActualHelpFunction(bool isCurrentAppWeb)),不要期望调用者在调用方法之前更改一堆标志。 - dummy
我同意,我的例子并不更好。我想要避免的事情是,让一个程序根据它运行的环境改变其行为。 这对你来说可能不是问题,但对于继承代码的下一个人来说可能会成为问题。他可能不知道行为会因运行上下文而改变。 阅读您其他的问题(https://dev59.com/fnA85IYBdhLWcg3wD_S8)使我的意图更加清晰。我只能赞同这个意图。 - LaustN

1
应用程序域包含关联配置文件的信息。由于Web应用程序的配置文件名为“web.config”,而其他所有应用程序的配置文件名为“{app}.exe.config”,因此这决定了应用程序的类型。
/// <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);
    }
}

0

你可以通过框架属性方便地完成它:

HostingEnvironment.IsHosted

引用 System.Web 并添加 System.Web.Hosting 命名空间。

当 IsHosted 为 true 时,表示宿主是 Web。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接