【问题标题】:Getting the date of a .NET assembly [duplicate]获取 .NET 程序集的日期 [重复]
【发布时间】:2011-01-04 06:10:27
【问题描述】:

如何从当前的 .NET 程序集中检索 Created 日期?

我想添加一些非常简单的功能,让我的应用在主程序集的构建日期一周后停止工作。我已经编写了在给定日期后杀死我的应用程序的代码。我只需要以编程方式从程序集中检索创建日期。

【问题讨论】:

    标签: c# .net-3.5


    【解决方案1】:

    这应该可行:

    var entryAssembly = Assembly.GetEntryAssembly();
    var fileInfo = new FileInfo(entryAssembly.Location);
    var buildDate = fileInfo.LastWriteTime;
    

    【讨论】:

      【解决方案2】:

      有什么问题:

      System.IO.File.GetLastWriteTime(Assembly.GetExecutingAssembly().Location);
      

      【讨论】:

      • 这好多了,因为我有多个 DLL 正在更新。谢谢!
      • 好多了。 GetCreationTime() 返回第一次创建程序集的时间。这不会返回上次创建程序集的时间。
      【解决方案3】:

      我不认为程序集本身包含它的创建日期。我怀疑你能得到的最接近的是程序集文件本身的创建日期:

      File.GetCreationTime(Assembly.GetExecutingAssembly().Location)
      

      应该可以解决问题。

      编辑:

      我认为 Jeff Atwood 的解决方案(由“手榴弹”在此线程中编写)可能是现在更好的方法。

      【讨论】:

      • 它在大多数情况下都有效,但如果尝试在 VSTO 解决方案(例如 Excel 插件)中使用它,他将始终得到今天的日期,因为正在将程序集文件复制到 AppData\Local \assembly 文件夹,然后在 Excel 中运行加载项。
      • 如果你把它复制到从 ftp 等下载它的网络也不起作用
      • 老实说,我认为手榴弹在此线程中编写的 Jeff Atwood 的解决方案现在可能是更好的方法。
      • GetLastWriteTime() 会更准确地了解它的构建时间。 GetCreationTime() 只会返回清理项目后创建的第一个构建
      • 不适用于通过反射(在内存中)创建的程序集。
      【解决方案4】:

      最好的方法是使用您在程序集的PreBuild 上设置的自定义属性。

      然后使用标准反射获取你创建的属性。

      但出于好奇,为什么要在 BUILD 日期之后终止应用?

      【讨论】:

      • 不需要是构建日期。我刚刚选择了那个日期,因为我知道该日期会随着应用程序的构建而自动更改。目标,我只想让应用程序运行大约一周。我也可以将日期硬编码到代码中,但需要在对应用程序进行更改时更改该变量。
      • @Scott 但比你杀死应用程序的方式更容易绕过。
      • 在非结构化环境(即互联网志愿者)中进行 alpha 测试时,根据构建日期终止应用程序似乎是一种减少噪音的好方法。这样,您就可以避免人们下载最新的 alpha 版,忘记它 3 周,然后测试和报告许多已经处理过的错误。它确保 Alpha 版测试人员始终使用最新版本的应用程序,而不会在该阶段引入更多错误,例如自动更新功能。
      • @Paul - 你是对的。它很容易被规避,但这与安全或复制保护无关。我需要一种快速而肮脏的方法来为构建设置过期日期。
      • 这是一个很好的答案。因为文件修改时间是绝对不可靠的。
      【解决方案5】:

      也许这个帖子on coding horror 可能会有所帮助

      【讨论】:

      • 更新了链接,虽然这里的其他几个答案做同样的事情或参考这篇文章的新位置
      【解决方案6】:

      以下基于:https://blog.codinghorror.com/determining-build-date-the-hard-way/

      public static class ApplicationInformation
      {
          /// <summary>
          /// Gets the executing assembly.
          /// </summary>
          /// <value>The executing assembly.</value>
          public static System.Reflection.Assembly ExecutingAssembly
          {
              get { return executingAssembly ?? (executingAssembly = System.Reflection.Assembly.GetExecutingAssembly()); }
          }
          private static System.Reflection.Assembly executingAssembly;
      
          /// <summary>
          /// Gets the executing assembly version.
          /// </summary>
          /// <value>The executing assembly version.</value>
          public static System.Version ExecutingAssemblyVersion
          {
              get { return executingAssemblyVersion ?? (executingAssemblyVersion = ExecutingAssembly.GetName().Version); }
          }
          private static System.Version executingAssemblyVersion;
      
          /// <summary>
          /// Gets the compile date of the currently executing assembly.
          /// </summary>
          /// <value>The compile date.</value>
          public static System.DateTime CompileDate
          {
              get
              {
                  if (!compileDate.HasValue)
                      compileDate = RetrieveLinkerTimestamp(ExecutingAssembly.Location);
                  return compileDate ?? new System.DateTime();
              }
          }
          private static System.DateTime? compileDate;
      
          /// <summary>
          /// Retrieves the linker timestamp.
          /// </summary>
          /// <param name="filePath">The file path.</param>
          /// <returns></returns>
          /// <remarks>http://www.codinghorror.com/blog/2005/04/determining-build-date-the-hard-way.html</remarks>
          private static System.DateTime RetrieveLinkerTimestamp(string filePath)
          {
              const int peHeaderOffset = 60;
              const int linkerTimestampOffset = 8;
              var b = new byte[2048];
              System.IO.FileStream s = null;
              try
              {
                  s = new System.IO.FileStream(filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read);
                  s.Read(b, 0, 2048);
              }
              finally
              {
                  if(s != null)
                      s.Close();
              }
              var dt = new System.DateTime(1970, 1, 1, 0, 0, 0).AddSeconds(System.BitConverter.ToInt32(b, System.BitConverter.ToInt32(b, peHeaderOffset) + linkerTimestampOffset));
              return dt.AddHours(System.TimeZone.CurrentTimeZone.GetUtcOffset(dt).Hours);
          }
      }
      

      【讨论】:

      • 这为 Assembly 类提供了一个很好的扩展方法。
      • 不适用于通过反射(在内存中)创建的程序集。那些没有位置(空字符串)。
      • 我不希望在内存程序集中找到编译日期,就像我不希望在小马身上找到斑马条纹一样。
      • 我喜欢这个,我最近唯一的变化是它在一个时区编译但部署在另一个时区(例如:在 Build Server 上编译并部署到 Azure)。在这种情况下,我修改了最后两行,如下所示:' var dateUtcKind = DateTime.SpecifyKind(dt, DateTimeKind.Utc);返回日期UtcKind;'
      • 很好,让我省了很多麻烦 :-)
      【解决方案7】:

      如果您正在使用紧凑型框架为移动设备编写应用程序,则 Assembly.Location 不可用。

      Here,我找到了替代方案:

           System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase)
      

      【讨论】:

        猜你喜欢
        • 2011-03-03
        • 1970-01-01
        • 2021-06-30
        • 1970-01-01
        • 2011-12-07
        • 2017-04-03
        • 2013-09-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多