【问题标题】:How can I get the current DateTime from the Precompiler in C#?如何从 C# 中的预编译器获取当前日期时间?
【发布时间】:2010-09-29 23:44:54
【问题描述】:

在 C# 3.0 中,我有一个属性,它应该包含类的版本。版本号只是编译的日期和时间。现在,我有以下代码:

public DateTime Version
{
    get { return DateTime.UtcNow; }
}

显然,这是错误的,因为此属性返回当前日期和时间。 那么,预编译器是否可以在编译时打印 DateTime?在这种情况下,我可以执行类似下面的操作。

public DateTime Version
{
    get { return new DateTime("PRECOMPILER DATE"); }
}

【问题讨论】:

    标签: c# .net c-preprocessor


    【解决方案1】:

    您可以从 dll 本身中检索它 (Source: codinghorror)

       private DateTime RetrieveLinkerTimestamp() {
            string filePath = System.Reflection.Assembly.GetCallingAssembly().Location;
            const int c_PeHeaderOffset = 60;
            const int c_LinkerTimestampOffset = 8;
            byte[] b = new byte[2048];
            System.IO.Stream 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();
                }
            }
    
            int i = System.BitConverter.ToInt32(b, c_PeHeaderOffset);
            int secondsSince1970 = System.BitConverter.ToInt32(b, i + c_LinkerTimestampOffset);
            DateTime dt = new DateTime(1970, 1, 1, 0, 0, 0);
            dt = dt.AddSeconds(secondsSince1970);
            dt = dt.AddHours(TimeZone.CurrentTimeZone.GetUtcOffset(dt).Hours);
            return dt;
        }
    

    【讨论】:

    • 源链接已过时(重定向到主页)?
    【解决方案2】:

    C# 没有宏的概念;但是,您可以在构建脚本(csproj / NANT / 等)中使用其他工具在源代码编译之前对其进行操作。例如,我使用它来将修订号设置为当前的 SVN 修订。

    一个廉价的选项是预构建事件(您可以通过 VS 中的项目属性对话框来执行此操作):本质上是一个在构建之前运行的 bat 文件;然后,您可以编写所需的任何更改。更复杂的选项是构建任务。

    例如,实用程序库here 包括一个Time 任务和一个FileUpdate 任务;它应该(理论上)可以将两者链接在一起以模拟您所需要的。

    就我个人而言,我会使用[AssemblyVersion] 的详细信息而不是时间 - 如果您将其链接到您的源代码控制系统,这将很容易找到有问题的版本;所以对于我的 SVN 版本,然后我使用(在我的构建项目中):

    <!-- See http://msbuildtasks.tigris.org -->
    <Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets"/>
    ...
    <SvnInfo LocalPath=".">
      <Output TaskParameter="Revision" PropertyName="BuildRev" />
    </SvnInfo>
    ...
    <FileUpdate Files="Path\To\My\AssemblyInfo.cs"
        Regex='(\[\s*assembly:\s*AssemblyVersion\(\s*"[^\.]+\.[^\.]+)\.([^\.]+)(\.)([^\.]+)("\)\s*\])'
        ReplacementText='$1.$2.$(BuildRev)$5' />
    <FileUpdate Files="Path\To\My\AssemblyInfo.cs"
        Regex='(\[\s*assembly:\s*AssemblyFileVersion\(\s*"[^\.]+\.[^\.]+)\.([^\.]+)(\.)([^\.]+)("\)\s*\])'
        ReplacementText='$1.$2.$(BuildRev)$5' />
    

    现在我的程序集版本是正确的,包括操作系统报告的文件版本。

    【讨论】:

    【解决方案3】:

    在 C# 中没有与 __TIME__ 预处理器指令等效的指令,最好的方法是获取当前程序集并获取创建日期,它将包含编译时间。见here

    【讨论】:

    • 该页面已被删除。
    【解决方案4】:

    我认为在 C# 中没有办法做到这一点 - C++ 风格的宏定义被明确禁止。

    您可以使用程序集的最后修改日期来解决它,或者可能包含一个文本文件作为嵌入式资源,并添加一个自定义构建操作,将当前日期/时间写入其中。

    【讨论】:

      【解决方案5】:

      没有预处理器__TIME__ 指令,但是您可以使用其他东西,例如程序集的创建时间。您也可以考虑使用源代码控制系统中的关键字替换(在 subversion 中为 $Date$)。

      【讨论】:

        【解决方案6】:

        Build 编号可以从程序集的元数据中检索,并且可以设置为与构建日期匹配。

        通常您会在 AssemblyInfo.cs 文件中找到或创建一个条目。使用 Visual Studio 创建项目时。一个例子:

        [assembly: AssemblyVersion("1.0.*")]
        

        AssemblyVersionAttribute 上的文档引用。 (我把一些重要的部分加粗了)

        你可以指定所有的值,或者你 可以接受默认的内部版本号, 修订号,或两者都使用 星号 ()。例如, [程序集:AssemblyVersion("2.3.25.1")] 表示 2 为主要版本, 3 为 次要版本,25 作为构建 编号,1 作为修订号。 版本号,例如 [程序集:AssemblyVersion("1.2.")] 将 1 指定为主要版本,将 2 指定为 次要版本,并接受 默认构建和修订号。一种 版本号如 [程序集:AssemblyVersion("1.2.15.*")] 将 1 指定为主要版本,将 2 指定为 次要版本,15 作为构建 编号,并接受默认值 修订号。 默认构建 数字每天递增。默认 修订号是随机的。

        如您所见,如果您可以使用此设置默认内部版本号。默认内部版本号是每天递增的值。

        然后您可以使用AssemblyName.Version 属性检索内部版本号。 MSDN 提供的示例应该可以帮助您。

        默认内部版本号是自 2000 年 1 月 1 日以来的天数。

        This question也有明​​确的说明如何使用这个。

        【讨论】:

        • 这不是真的,内部版本号可以是你想要的任何东西,并且在实际发布时可能会改变。您不能依靠您的内部版本号来知道编译发生的时间。
        • 是的,内部版本号可以是任何您想要的,但默认内部版本号,即版本中使用“*”生成的版本号是自 2000 年 1 月 1 日以来的天数
        • 我的回答更清楚了。我希望现在用户设置的内部版本号和生成的默认内部版本号之间没有混淆。
        • 即使人们使用默认的内部版本号,每天的增量也只能提供构建日期。 OP 要求提供日期和时间,
        【解决方案7】:

        您是否正在寻找类似的东西:
        (通过 Version-Info 获取构建程序集的日期;Build-Number 是自 1.1.2000 以来的天数)

                 var version = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
                DateTime versionsDatum = new DateTime(2000, 1, 1);
                versionsDatum = versionsDatum.AddDays(version.Build);
        

        【讨论】:

          猜你喜欢
          • 2020-01-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-10-18
          • 2011-01-01
          • 2020-05-06
          相关资源
          最近更新 更多