【问题标题】:Programmatically get the version number of a DLL以编程方式获取 DLL 的版本号
【发布时间】:2010-12-17 20:24:38
【问题描述】:

是否可以从任何 .NET DLL 以编程方式获取版本号?

如果是,怎么做?

【问题讨论】:

标签: c# .net


【解决方案1】:

您可以使用 System.Reflection.Assembly.Load*() 方法,然后获取它们的 AssemblyInfo。

【讨论】:

    【解决方案2】:
    Assembly assembly = Assembly.LoadFrom("MyAssembly.dll");
    Version ver = assembly.GetName().Version;
    

    重要: 应该注意的是,这不是对原始问题的最佳答案。不要忘记在此页面上阅读更多内容。

    【讨论】:

    • 这会将 MyAssembly.dll 加载到正在运行的 AppDomain... 坏主意。
    • 我推荐Assemblyname.GetAssemblyName 来避免这些问题
    • 将程序集加载到appdomain中很慢,不可逆(你不能在不杀掉域的情况下卸载它),需要权限并且容易引起副作用,例如执行beforefieldinit类型初始化程序,并且在这种情况下不需要。这些理由够充分吗?
    • @staafl:是的;不仅为我,也为以后阅读此页面的其他人。
    • FileVersionInfo.GetVersionInfo("foo.dll").FileVersion 做得很好,不会将 dll 加载到应用程序中。
    【解决方案3】:

    为已启动的程序集获取它(winform、控制台应用程序等...)

    using System.Reflection;
    ...
    Assembly.GetEntryAssembly().GetName().Version
    

    【讨论】:

    • GetExecutingAssembly() 也可能有帮助。
    【解决方案4】:

    Kris,您的版本在需要从实际的 DLL 文件加载程序集时效果很好(如果 DLL 存在的话!),但是,如果 DLL 是嵌入的(即不是文件),则会收到一个非常不需要的错误而是一个嵌入式 DLL)。

    另一件事是,如果使用类似“1.2012.0508.0101”之类的版本控制方案,则当您获取版本字符串时,您实际上会得到“1.2012.518.101强>"; 注意缺少的零

    所以,这里有一些额外的函数来获取 DLL 的版本(嵌入的或从 DLL 文件中):

        public static System.Reflection.Assembly GetAssembly(string pAssemblyName)
        {
            System.Reflection.Assembly tMyAssembly = null;
    
            if (string.IsNullOrEmpty(pAssemblyName)) { return tMyAssembly; }
            tMyAssembly = GetAssemblyEmbedded(pAssemblyName);
            if (tMyAssembly == null) { GetAssemblyDLL(pAssemblyName); }
    
            return tMyAssembly;
        }//System.Reflection.Assembly GetAssemblyEmbedded(string pAssemblyDisplayName)
    
    
        public static System.Reflection.Assembly GetAssemblyEmbedded(string pAssemblyDisplayName)
        {
            System.Reflection.Assembly tMyAssembly = null;
    
            if(string.IsNullOrEmpty(pAssemblyDisplayName)) { return tMyAssembly; }
            try //try #a
            {
                tMyAssembly = System.Reflection.Assembly.Load(pAssemblyDisplayName);
            }// try #a
            catch (Exception ex)
            {
                string m = ex.Message;
            }// try #a
            return tMyAssembly;
        }//System.Reflection.Assembly GetAssemblyEmbedded(string pAssemblyDisplayName)
    
    
        public static System.Reflection.Assembly GetAssemblyDLL(string pAssemblyNameDLL)
        {
            System.Reflection.Assembly tMyAssembly = null;
    
            if (string.IsNullOrEmpty(pAssemblyNameDLL)) { return tMyAssembly; }
            try //try #a
            {
                if (!pAssemblyNameDLL.ToLower().EndsWith(".dll")) { pAssemblyNameDLL += ".dll"; }
                tMyAssembly = System.Reflection.Assembly.LoadFrom(pAssemblyNameDLL);
            }// try #a
            catch (Exception ex)
            {
                string m = ex.Message;
            }// try #a
            return tMyAssembly;
        }//System.Reflection.Assembly GetAssemblyFile(string pAssemblyNameDLL)
    
    
        public static string GetVersionStringFromAssembly(string pAssemblyDisplayName)
        {
            string tVersion = "Unknown";
            System.Reflection.Assembly tMyAssembly = null;
    
            tMyAssembly = GetAssembly(pAssemblyDisplayName);
            if (tMyAssembly == null) { return tVersion; }
            tVersion = GetVersionString(tMyAssembly.GetName().Version.ToString());
            return tVersion;
        }//string GetVersionStringFromAssemblyEmbedded(string pAssemblyDisplayName)
    
    
        public static string GetVersionString(Version pVersion)
        {
            string tVersion = "Unknown";
            if (pVersion == null) { return tVersion; }
            tVersion = GetVersionString(pVersion.ToString());
            return tVersion;
        }//string GetVersionString(Version pVersion)
    
    
        public static string GetVersionString(string pVersionString)
        {
            string tVersion = "Unknown";
            string[] aVersion;
    
            if (string.IsNullOrEmpty(pVersionString)) { return tVersion; }
            aVersion = pVersionString.Split('.');
            if (aVersion.Length > 0) { tVersion = aVersion[0]; }
            if (aVersion.Length > 1) { tVersion += "." + aVersion[1]; }
            if (aVersion.Length > 2) { tVersion += "." + aVersion[2].PadLeft(4, '0'); }
            if (aVersion.Length > 3) { tVersion += "." + aVersion[3].PadLeft(4, '0'); }
    
            return tVersion;
        }//string GetVersionString(Version pVersion)
    
    
        public static string GetVersionStringFromAssemblyEmbedded(string pAssemblyDisplayName)
        {
            string tVersion = "Unknown";
            System.Reflection.Assembly tMyAssembly = null;
    
            tMyAssembly = GetAssemblyEmbedded(pAssemblyDisplayName);
            if (tMyAssembly == null) { return tVersion; }
            tVersion = GetVersionString(tMyAssembly.GetName().Version.ToString());
            return tVersion;
        }//string GetVersionStringFromAssemblyEmbedded(string pAssemblyDisplayName)
    
    
        public static string GetVersionStringFromAssemblyDLL(string pAssemblyDisplayName)
        {
            string tVersion = "Unknown";
            System.Reflection.Assembly tMyAssembly = null;
    
            tMyAssembly = GetAssemblyDLL(pAssemblyDisplayName);
            if (tMyAssembly == null) { return tVersion; }
            tVersion = GetVersionString(tMyAssembly.GetName().Version.ToString());
            return tVersion;
        }//string GetVersionStringFromAssemblyEmbedded(string pAssemblyDisplayName)
    

    【讨论】:

      【解决方案5】:
      var versionAttrib = new AssemblyName(Assembly.GetExecutingAssembly().FullName);
      

      【讨论】:

        【解决方案6】:

        这是一个很好的方法,使用一点反射来获取包含特定类的 DLL 版本:

        var ver = System.Reflection.Assembly.GetAssembly(typeof(!Class!)).GetName().Version;
        

        只需替换 !Class!使用在您希望获取其版本的 DLL 中定义的类的名称。

        这是我的首选方法,因为如果我为不同的部署移动 DLL,我不必更改文件路径。

        【讨论】:

        • 请注意,这仅在当前程序集静态引用了相关程序集时才有效。
        • 这是最好的答案,因为 DLL 不一定是入口程序集,甚至不是调用它的程序集
        • 查看stackoverflow.com/a/909583/492 获取不同类型的版本信息。例如FileVersionInfo
        【解决方案7】:

        如果 dll 是 .netWin32,则此方法有效。反射方法仅在 dll 为 .net 时才有效。此外,如果您使用反射,则需要将整个 dll 加载到内存中。以下方法不会将程序集加载到内存中。

        // Get the file version.
        FileVersionInfo myFileVersionInfo = FileVersionInfo.GetVersionInfo(@"C:\MyAssembly.dll");
        
        // Print the file name and version number.
        Console.WriteLine("File: " + myFileVersionInfo.FileDescription + '\n' +
                          "Version number: " + myFileVersionInfo.FileVersion);
        

        发件人:http://msdn.microsoft.com/en-us/library/system.diagnostics.fileversioninfo.fileversion.aspx

        original source

        【讨论】:

        • 我喜欢这个。你为什么还要费心加载 dll 然后使用反射来获取版本,而你真正想做的只是这个???
        • @ben,你能编辑帖子吗?我看到我因添加反对票而失去了 -1 代表,我不记得做过。它不会让我改变它,除非你编辑帖子。干杯!
        • 如果您想确保获得当前正在使用的可执行文件/dll:而不是静态文件名(上面的@"C:\MyAssembly.dll"),您可以使用System.Reflection.Assembly.GetExecutingAssembly().Location(或者如果是dll: Assembly.GetAssembly(typeof(AClassInTheDll)).Location)
        • 这是 AssemblyVersion 和 AssemblyFileVersion 属性的区别。 AssemblyFileVersion 以 Windows API 可以获取值的方式获得标记。 AssemblyVersion 是强名称的一部分,不一定与 AssemblyFileVersion 相同。
        【解决方案8】:

        首先,您可能对以下两种可能的“版本”感兴趣:

        • Windows文件系统文件版本,适用于所有可执行文件

        • Assembly build 版本,由编译器嵌入到 .NET 程序集中(显然只适用于 .NET 程序集 dll 和 exe 文件)

        在前一种情况下,您应该使用 Ben Anderson 的答案;在后一种情况下,请使用 AssemblyName.GetAssemblyName(@"c:\path\to\file.dll").Version 或 Tataro 的答案,以防您的代码引用程序集。

        请注意,您可以忽略所有使用 .Load()/.LoadFrom() 方法的答案,因为它们实际上会在当前 AppDomain 中加载程序集 - 这类似于砍树以查看它的年龄。

        【讨论】:

          【解决方案9】:

          虽然最初的问题可能并非特定于 Web 服务,但您可以添加一个完整的 testWebService 以显示 Web 服务非缓存响应和文件版本。我们使用文件版本而不是程序集版本,因为我们想知道一个版本,但是对于所有程序集版本 1.0.0.0,网站可以轻松修补(签名和需求链接仍然有效!)。将 @Class@ 替换为嵌入此服务的 Web api 控制器的名称。这对于 Web 服务上的 go/nogo 以及快速版本检查非常有用。

            [Route("api/testWebService")]
            [AllowAnonymous]
            [HttpGet]
            public HttpResponseMessage TestWebService()
            {
                HttpResponseMessage responseMessage = Request.CreateResponse(HttpStatusCode.OK);
                string loc = Assembly.GetAssembly(typeof(@Class@)).Location;
                FileVersionInfo versionInfo = FileVersionInfo.GetVersionInfo(loc);
                responseMessage.Content = new StringContent($"<h2>The XXXXX web service GET test succeeded.</h2>{DateTime.Now}<br/><br/>File Version: {versionInfo.FileVersion}");
                responseMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("text/html");
                Request.RegisterForDispose(responseMessage);
                return responseMessage;
            }
          

          我发现还需要在配置下的 web.config 中添加以下内容以使其真正匿名

          <location path="api/testwebservice">
              <system.web>
                  <authorization>
                      <allow users="*" />
                  </authorization>
              </system.web>
          </location>
          

          【讨论】:

            【解决方案10】:

            @Ben 的回答对我很有用。但我需要检查产品版本,因为它是我的软件中发生的主要增量,并遵循语义版本控制。

            myFileVersionInfo.ProductVersion
            

            这个方法符合我的期望

            更新:我们可以使用 Assembly 获取产品版本,而不是在程序中明确提及 dll 路径(根据生产版本的需要)。

            Assembly assembly = Assembly.GetExecutingAssembly();
            FileVersionInfo fileVersionInfo =FileVersionInfo.GetVersionInfo(assembly.Location); 
            string ProdVersion= fileVersionInfo.ProductVersion;
            

            【讨论】:

            • 注意:如果版本包含自动递增值的星号,则此方法将返回星号而不是实际生成的数字(即,如果您在程序集信息中输入 1.0.* 则不起作用)。
            • 是的!但是,我选择了Jeniks自动化进行版本升级,所以程序集总是有完美的dll版本组合。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2015-10-12
            • 1970-01-01
            • 2010-10-30
            • 2016-09-16
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多