2009-01-07 145 views
6

在C#3.0中,我有一个属性假设包含该类的版本。版本号只是编译的日期和时间。现在,我有以下代码:如何从C#中的预编译器获取当前日期时间?

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

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

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

回答

7

C#没有宏的概念;但是,您可以在构建脚本(csproj/NANT/etc)中使用其他工具在编译之前对源进行操作。例如,我使用它来将版本号设置为当前的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' /> 

现在我组装的版本是正确的,包括获取由OS发送的文件版本。

+0

我做类似的东西来这MSBuild使用Microsoft SDC任务:http://www.codeplex.com/sdctasks – 2009-01-07 09:18:13

3

C#中的__TIME__预处理器指令没有等价物,您可以做的最好的方法是获取当前程序集并获取创建的日期,它将包含编译时间。请参阅here

0

我不认为有一种方法可以在C#中执行此操作 - C++样式的宏定义被明确禁止。

您可以使用程序集的上次修改日期来解决该问题,也可以将文本文件包含为嵌入式资源,并添加将当前日期/时间写入其中的自定义构建操作。

0

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

8

可以从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; 
    } 
+0

有趣的链接...谢谢。 – 2009-01-07 08:42:59

+0

不客气:) – Stormenet 2009-01-07 15:29:12

-1

Build数目可以从一个组件的元数据来检索retreive它,并且可以被设定成与构建日期。

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

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

关于AssemblyVersionAttribute的文档报价。 (我加粗了一些重要的零部件)

您可以指定所有这些值,也 可以通过使用 星号()接受默认的内部版本号, 版本号,或两者兼而有之。例如, [assembly: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也对如何使用这一点有明确的解释。

-1

你寻找的是这样的:
(获取是通过版本 - 信息建设大会的日期;集结号是自2000年1月1日天)

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