6

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

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

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

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

7 回答 7

8

您可以从 dll 本身中检索它(来源: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;
    }
于 2009-01-07T08:31:45.790 回答
7

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

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

例如,这里的实用程序库包括一个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' />

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

于 2009-01-07T07:53:54.227 回答
3

C#中的预处理器指令没有等效__TIME__项,您可以做的最好的事情是获取当前程序集并获取创建日期,它将包含编译时间。看这里

于 2009-01-07T07:58:45.153 回答
0

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

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

于 2009-01-07T08:02:23.087 回答
0

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

于 2009-01-07T08:13:13.190 回答
-1

可以从程序集的元数据中检索内部版本号,并且可以将其设置为与构建日期相匹配

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

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

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

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

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

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

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

这个问题对如何使用它也有明确的解释。

于 2009-01-07T08:47:56.660 回答
-1

您是否正在寻找这样的东西:(
通过 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);
于 2009-08-28T08:17:33.250 回答