我目前有一个应用程序显示构建号在其标题窗口。这很好,除了它对大多数用户没有任何意义,他们想知道他们是否有最新的版本-他们倾向于将其称为“上周四的”而不是1.0.8.4321版本。

计划是把构建日期放在那里,例如“App构建于21/10/2009”。

我正在努力寻找一种程序化的方法,将构建日期作为文本字符串提取出来,以便像这样使用。

对于版本号,我使用:

Assembly.GetExecutingAssembly().GetName().Version.ToString()

在定义了这些是怎么来的之后。

我希望编译日期(和时间,为了加分)也像这样。

非常感谢这里的指示(如果合适的话,借口双关语),或者更整洁的解决方案……


当前回答

我只会:

File.GetCreationTime(GetType().Assembly.Location)

其他回答

将以下内容添加到预构建事件命令行:

echo %date% %time% > "$(ProjectDir)\Resources\BuildDate.txt"

添加这个文件作为资源,现在你有'BuildDate'字符串在你的资源。

在将文件插入资源(作为公共文本文件)后,我通过

string strCompTime = Properties.Resources.BuildDate;

若要创建资源,请参见如何在. net中创建和使用资源。

如果将程序集复制到另一个位置,则不会更改GetLastWriteTime。

public static class AssemblyExtensions
{
    public static DateTime GetLinkerTime(this Assembly assembly)
    {
        return File.GetLastWriteTime(assembly.Location).ToLocalTime();
    }
}

另一种不同的pcl友好的方法是使用MSBuild内联任务将构建时间替换为应用程序上的属性返回的字符串。我们在一个具有Xamarin的应用程序中成功地使用了这种方法。形式,Xamarin的。Android和Xamarin。iOS项目。

编辑:

通过将所有逻辑移动到SetBuildDate来简化。目标文件,并使用Regex而不是简单的字符串替换,这样文件可以在每次构建时修改而不“重置”。

MSBuild内联任务定义(保存在SetBuildDate中。目标文件本地到Xamarin。本例中的表单项目):

<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' ToolsVersion="12.0">

  <UsingTask TaskName="SetBuildDate" TaskFactory="CodeTaskFactory" 
    AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v12.0.dll">
    <ParameterGroup>
      <FilePath ParameterType="System.String" Required="true" />
    </ParameterGroup>
    <Task>
      <Code Type="Fragment" Language="cs"><![CDATA[

        DateTime now = DateTime.UtcNow;
        string buildDate = now.ToString("F");
        string replacement = string.Format("BuildDate => \"{0}\"", buildDate);
        string pattern = @"BuildDate => ""([^""]*)""";
        string content = File.ReadAllText(FilePath);
        System.Text.RegularExpressions.Regex rgx = new System.Text.RegularExpressions.Regex(pattern);
        content = rgx.Replace(content, replacement);
        File.WriteAllText(FilePath, content);
        File.SetLastWriteTimeUtc(FilePath, now);

   ]]></Code>
    </Task>
  </UsingTask>

</Project>

在Xamarin中调用上述内联任务。在目标BeforeBuild中形成csproj文件:

  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
       Other similar extension points exist, see Microsoft.Common.targets.  -->
  <Import Project="SetBuildDate.targets" />
  <Target Name="BeforeBuild">
    <SetBuildDate FilePath="$(MSBuildProjectDirectory)\BuildMetadata.cs" />
  </Target>

FilePath属性被设置为Xamarin中的BuildMetadata.cs文件。表单项目,包含一个简单的类,具有字符串属性BuildDate,构建时间将被替换为:

public class BuildMetadata
{
    public static string BuildDate => "This can be any arbitrary string";
}

将此文件BuildMetadata.cs添加到项目中。它将在每次构建时被修改,但是以一种允许重复构建的方式(重复替换),因此您可以根据需要在源代码控制中包含或省略它。

使用下面的代码。

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

它将返回最后一个dll的创建日期。如果调试正在运行,则它将显示当前日期和时间。我修改了其中一个答案的一些代码,因为我不能评论答案。请评论进一步讨论。

对于。net 5,我已经成功地使用了这种方法。(在这里找到)。

把这个添加到.csproj文件中:

<SourceRevisionId>build$([System.DateTime]::UtcNow.ToString("yyyyMMddHHmmss"))</SourceRevisionId>

获取构建日期的方法:

private static DateTime GetBuildDate(Assembly assembly)
{
    const string BuildVersionMetadataPrefix = "+build";

    var attribute = assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>();
    if (attribute?.InformationalVersion != null)
    {
        var value = attribute.InformationalVersion;
        var index = value.IndexOf(BuildVersionMetadataPrefix);
        if (index > 0)
        {
            value = value.Substring(index + BuildVersionMetadataPrefix.Length);
            if (DateTime.TryParseExact(value, "yyyyMMddHHmmss", CultureInfo.InvariantCulture, DateTimeStyles.None, out var result))
            {
                return result;
            }
        }
    }

    return default;
}

用法:

 var buildTime = GetBuildDate(Assembly.GetExecutingAssembly());
 buildTime = buildTime.ToLocalTime();