代码之家  ›  专栏  ›  技术社区  ›  David Duffett

使用程序集(ASP.NET/C)中的Web应用程序版本号

  •  52
  • David Duffett  · 技术社区  · 17 年前

    如何获取引用程序集中调用的Web应用程序的版本号?

    我试过使用system.reflection.assembly.getcallingaassembly().getname(),但它只提供动态编译的程序集(返回0.0.0.0的版本号)。

    更新:在我的例子中,我需要一个不需要引用Web应用程序集中的类的解决方案。下面杰森的回答(标记为“接受”)满足了这一要求——这里提交的其他很多答案都不满足。

    11 回复  |  直到 10 年前
        1
  •  48
  •   Jason Duffett    13 年前

    下面是我使用的一些代码,它支持从Web或非Web应用程序获取应用程序的“主”程序集,然后可以使用getname().version获取版本。

    它首先尝试对非Web应用程序使用getEntryassembly()。这将在ASP.NET下返回空值。 然后查看httpContext.current以确定这是否是Web应用程序。然后,它使用当前httphandler的类型-但如果使用aspx页进行调用,则此类型的程序集可能是生成的ASP.NET程序集,因此它将遍历httphandler的baseType链,直到找到不在ASP.NET用于生成类型(“asp”)的命名空间中的类型。 这通常是主程序集中的一个类型(例如代码隐藏文件中的页面)。然后我们可以使用这种类型的程序集。 如果所有其他操作都失败,则返回到getExecutingAssembly()。

    这种方法仍然存在潜在的问题,但它在我们的应用程序中有效。

        private const string AspNetNamespace = "ASP";
    
        private static Assembly getApplicationAssembly()
        {
            // Try the EntryAssembly, this doesn't work for ASP.NET classic pipeline (untested on integrated)
            Assembly ass = Assembly.GetEntryAssembly();
    
            // Look for web application assembly
            HttpContext ctx = HttpContext.Current;
            if (ctx != null)
                ass = getWebApplicationAssembly(ctx);
    
            // Fallback to executing assembly
            return ass ?? (Assembly.GetExecutingAssembly());
        }
    
        private static Assembly getWebApplicationAssembly(HttpContext context)
        {
            Guard.AgainstNullArgument(context);
    
            object app = context.ApplicationInstance;
            if (app == null) return null;
    
            Type type = app.GetType();
            while (type != null && type != typeof(object) && type.Namespace == AspNetNamespace)
                type = type.BaseType;
    
            return type.Assembly;
        }
    

    更新: 我已将此代码汇总到一个小项目中 GitHub NuGet .

        2
  •  35
  •   Yodan Tauber    15 年前

    我发现获得“主”程序集(而不是动态程序集)版本的最简单的一种线性方法是:

    typeof(MyMainClass).Assembly.GetName().Version
    

    使用顶级类,它不太可能“改变其含义”,也不可能作为重构工作的一部分被替换,例如 MyMainClass . 您知道这个类是在哪个程序集中定义的,并且对于版本号来自何处不再有混淆。

        3
  •  26
  •   Random Developer    10 年前

    我更喜欢web.config来存储站点的当前版本。

    您还可以尝试在Web应用程序根目录中创建具有以下内容的assemblyinfo.cs文件:

    using System.Reflection;
    using System.Runtime.CompilerServices;
    ...
    [assembly: AssemblyVersion("1.0.*")]
    ...
    

    然后通过如下代码访问值:

    System.Reflection.Assembly.GetExecutingAssembly()
    

    这里还有更多 informaiton 在assemblyinfo类上。

        4
  •  14
  •   Amir Khawaja    16 年前

    添加到已发布的响应程序。为了在ASP.NET Web应用程序中获取程序集版本,需要在代码隐藏文件中放置一个方法,类似于:

    protected string GetApplicationVersion() {
        return System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
    }
    

    在ASPX页面中,您只需在以下位置显示版本号:

    <%= GetApplicationVersion() %>
    
        5
  •  8
  •   Amal Dev    13 年前

    以防万一有人仍然感兴趣;这应该是个骗局,而且应该比仅仅采取 BaseType 属于 ApplicationInstance 掌握global.asax的实现。

    global.asax总是编译为与assemblyinfo.cs中的assembly属性相同的程序集,因此这对于定义global.asax的所有Web应用程序都有效。

    对于那些没有定义自己的global.asax的用户,它将返回到生成的版本 global_asax 类型,它始终是0.0.0.0,对于不是Web应用程序的应用程序,它将完全不返回任何版本。

    奖金;使用 BuildManager 类做 需要活动的 HttpContext 实例,这意味着您也应该能够从应用程序启动代码中使用它。

    public static Version GetHttpApplicationVersion() {
      Type lBase = typeof(HttpApplication);
      Type lType = BuildManager.GetGlobalAsaxType();
    
      if (lBase.IsAssignableFrom(lType))
      {
        while (lType.BaseType != lBase) { lType = lType.BaseType; }
        return lType.Assembly.GetName().Version;
      }
      else
      {
        return null;
      }
    }
    
        6
  •  6
  •   Andrei Schneider    14 年前

    httpContext.current.applicationInstance是从global.asax.cs中的类派生的。您可以执行以下操作

     var instance = HttpContext.Current.ApplicationInstance;
     Assembly asm = instance.GetType().BaseType.Assembly;
     System.Version asmVersion = asm.GetName().Version;
    

    它同时在ASP.NET(ASPX)和ASP.NET MVC中工作

        7
  •  4
  •   kbrimington    15 年前

    我遇到了一个类似的问题,认为您可能会发现解决方案是有用的。

    我需要从一个自定义服务器控件报告当前应用程序版本(Web应用程序项目),其中服务器控件包含在另一个库中。问题是“最简单”的装配getter没有提供正确的装配。

    • Assembly.GetExecutingAssembly() 返回包含控件的程序集,而不是应用程序程序集。
    • Assembly.GetCallingAssembly() 根据我在调用树中的位置返回不同的程序集;通常是System.Web,有时还返回包含控件的程序集。
    • Assembly.GetEntryAssembly() 返回 null .
    • new StackTrace().GetFrames()[idx].GetMethod().DeclaringType.Assembly 在索引处检索堆栈跟踪中帧的程序集 idx ;但是,除了不美观、昂贵且容易对帧索引进行错误计算外,堆栈跟踪还可能 不包含 对应用程序集的任何调用。
    • Assembly.GetAssembly(Page.GetType()) 给我打分 App_Web_@#$@#$%@ 包含动态生成的页的程序集。当然,动态页面从我的应用程序集继承了一个类,这样就得到了最终的解决方案:

    Assembly.GetAssembly(Page.GetType().BaseType)
    

    使用手头的程序集引用,可以通过其名称钻取到版本:

    var version = Assembly.GetAssembly(Page.GetType().BaseType)
                          .GetName()
                          .Version;
    

    现在,这个解决方案可以工作了,因为我从应用程序集引用了一个类型。我们不使用任何这样的页面 从代码背后继承,所以它对我们来说是有效的,但是如果您的组织的编码实践不同,您的里程可能会有所不同。

    快乐编码!

        8
  •  2
  •   Rob    15 年前
    Version version = new Version(Application.ProductVersion);
    string message = version.ToString();
    
        9
  •  1
  •   Seiti    16 年前

    这里有一些信息: http://www.velocityreviews.com/forums/showpost.php?p=487050&postcount=8

    在ASP.NET 2.0中,每个页面都内置到自己的程序集中,因此只有dll assemblyinfo.cs内置于will中 返回正确答案。只添加一个 assemblyinfo.cs的静态方法 返回版本信息,然后调用 此方法来自您的其他页面。

    --布鲁斯(sqlwork.com)

    但我写了一个简单的方法:

        public static string GetSystemVersion(HttpServerUtility server)
        {
            System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
            doc.Load(server.MapPath("~/web.config"));
            System.Xml.XmlNamespaceManager ns = new System.Xml.XmlNamespaceManager(doc.NameTable);
            ns.AddNamespace("bla", "http://schemas.microsoft.com/.NetConfiguration/v2.0");
    
            System.Xml.XmlNode node = doc.SelectSingleNode("/bla:configuration/bla:system.web/bla:authentication/bla:forms[@name]", ns);
    
            string projectName = "";
            if (node != null && node.Attributes != null && node.Attributes.GetNamedItem("name") != null)
                projectName = node.Attributes.GetNamedItem("name").Value; //in my case, that value is identical to the project name (projetname.dll)
            else
                return "";
    
            Assembly assembly = Assembly.Load(projectName);
            return assembly.GetName().Version.ToString();
        }
    
        10
  •  1
  •   Matt Woodard    16 年前

    如果您是从Web控件中查找此代码,则有一种方法是查找代码隐藏页的类型(即继承自System.Web.UI.Page的类)。这通常在消费者的Web部件中。

    Type current, last;
    current = Page.GetType();
    do
    {
        last = current;
        current = current.BaseType;
    } while (current != null && current != typeof(System.Web.UI.Page));
    return last;
    

    我希望有更好的方法。

        11
  •  1
  •   Tom Deloford    10 年前

    这个问题说明 没有参考 (实例)它并没有(最初)说不知道Web应用程序类型。

    编辑 OP澄清说,是的,它们确实不需要对调用Web程序集中的类型有任何了解,因此答案是适当的。但是,我会认真考虑重构这样一个解决方案,以便将版本传递到另一个程序集中。

    对于此方案中的大多数人,如果您知道自定义httpapplication类型:

     typeof(MyHttpApplication).Assembly.GetName().Version
    

    如果只有动态生成类型:

     typeof(DynamiclyGeneratedTypeFromWebApp).BaseType.Assembly.GetName().Version
    

    停止投票给我这个答案:)