如何在设计时自动插入构建日期?

11

希望标题有所描述。

我有一个用C#和.net 2.0编写的winform应用程序。我希望自动更新上次编译日期到一个变量中,以便在关于框和初始闪屏框中使用。目前我手动更新一个字符串变量。有没有办法实现这个功能?

VS2008 .net 2.0 c#

5个回答

7

另一个技巧(可能不适用于您)是利用.NET生成的自动构建和修订号。 如果您的AssemblyInfo包含:

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

最后两个数字只是日期/时间戳。以下代码(下面列表中)可能有所帮助:
Version v = Assembly.GetExecutingAssembly().GetName().Version;
DateTime compileDate = new DateTime((v.Build - 1) * TimeSpan.TicksPerDay + v.Revision * TimeSpan.TicksPerSecond * 2).AddYears(1999);

编辑:这里有一个替代答案,可能比我提供的更容易理解: https://dev59.com/83RA5IYBdhLWcg3w2xsI#804895

意思是:这里提供了一个备选答案,可能比我提供的更容易理解。请点击链接查看。

1
注意!此代码在2012年3月11日构建时无法工作(因为闰年的原因?):它返回3月12日而不是3月11日。 - JYL

5
把这个放到你的预构建事件中:
echo public static class DateStamp { public readonly static System.DateTime BuildTime = System.DateTime.Parse("%date%"); }  > $(ProjectDir)DateStamp.cs

它创建了一个名为DateStamp的类,就像这样;
public static class DateStamp
{ 
   public readonly static System.DateTime BuildTime = System.DateTime.Parse("14/12/2009"); 
}

你可以像这样使用它:

Console.WriteLine("Build on " + DateStamp.BuildTime.ToShortDateString());

我该如何在构建之前让它识别“DateStamp”?我收到错误消息...当前上下文中不存在名称“DateStamp”。 - Brad
啊,没错。文件(DateStamp.cs)将位于项目的根目录中。在VS中,进入解决方案资源管理器,单击显示所有文件的按钮,包括当前未在项目中的文件。找到DateStamp.cs,右键单击它,并选择“包含到项目中”。现在应该能够作为项目的一部分进行构建了。 - Steve Cooper

3
这可能晚了十年,但或许能帮助其他人。你可以将以下目标添加到你的csproj文件中,在结尾处粘贴即可:
 <Target Name="BuildDate" BeforeTargets="CoreCompile">
    <PropertyGroup>
      <SharedAssemblyInfoFile>$(IntermediateOutputPath)CustomAssemblyInfo.cs</SharedAssemblyInfoFile>
    </PropertyGroup>
    <ItemGroup>
      <Compile Include="$(SharedAssemblyInfoFile)" />
    </ItemGroup>
    <ItemGroup>
      <AssemblyAttributes Include="AssemblyMetadata">
        <_Parameter1>AssemblyDate</_Parameter1>
        <_Parameter2>$([System.DateTime]::UtcNow.ToString("u"))</_Parameter2>
      </AssemblyAttributes>
    </ItemGroup>
    <WriteCodeFragment Language="C#" OutputFile="$(SharedAssemblyInfoFile)" AssemblyAttributes="@(AssemblyAttributes)" />
  </Target>

这将在您的“obj”文件夹中创建一个CustomAssemblyInfo.cs文件,其中包含一行:[assembly: AssemblyMetadata("AssemblyDate", "DATE_OF_BUILD_HERE")] 此文件将编译到您的程序集中,因此您可以使用反射在运行时访问它,例如以下代码:

using System;
using System.Linq;
using System.Reflection;

public class Application
{
    static DateTime BuildDate;
    public static DateTime GetBuildDate()
    {
        if (BuildDate == default(DateTime)) {
            var attr = typeof(Application).Assembly.GetCustomAttributes<AssemblyMetadataAttribute>();
            var dateStr = attr.Single(a => a.Key == "AssemblyDate")?.Value;
            BuildDate = DateTime.Parse(dateStr);
        }
        return BuildDate;
    }
}

需要注意的一点是,我在这里使用的AssemblyMetadataAttribute仅在.NET 4.5.3中添加,因此如果您需要支持低于该版本的版本,则可以定义自己的自定义属性类型来保存日期值。


这个解决方案很棒...但是我在一个传统的ASP.NET WebForms项目中使用它,似乎会破坏“发布”构建(VS抱怨缺少AssemblyMetadataAttribute的参数)-但奇怪的是,如果我先进行初始正常项目构建,然后再进行发布构建,它就可以工作。奇怪。 - Dai
1
这是一个程序相关的内容:System.InvalidOperationException: 'Sequence contains no matching element' - Jerryno

1

我使用了来自codeproject.com的这个关于框。它实际上是由Jeff Atwood在2004年编写的。它通过查看程序集文件的日期戳或从程序集版本计算来确定编译时间。也许你可以从中提取相关的代码。


0

这方面没有内置的宏或类似的东西。你最好的选择可能是使用自定义构建任务,例如在tigris上,使用Time任务和RegexReplace或类似的任务。不容易做到正确。个人而言,我使用存储库版本来更新AssemblyInfo - 广义相关?

<Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets"/>
...
<SvnInfo LocalPath=".">
  <Output TaskParameter="Revision" PropertyName="BuildRev" />
</SvnInfo>
<FileUpdate Files="protobuf-net\Properties\AssemblyInfo.cs"
        Regex='(\[\s*assembly:\s*AssemblyVersion\(\s*"[^\.]+\.[^\.]+)\.([^\.]+)(\.)([^\.]+)("\)\s*\])'
        ReplacementText='$1.$2.$(BuildRev)$5' />

我不同意这种方法,因为我认为构建过程不应该改变源文件。 - MarkPflug

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接