I currently have an app displaying the build number in its title window. That\'s well and good except it means nothing to most of the users, who want to know if they have t
it could be
Assembly execAssembly = Assembly.GetExecutingAssembly();
var creationTime = new FileInfo(execAssembly.Location).CreationTime;
// "2019-09-08T14:29:12.2286642-04:00"
You can use this project: https://github.com/dwcullop/BuildInfo
It leverages T4 to automate the build date timestamp. There are several versions (different branches) including one that gives you the Git Hash of the currently checked out branch, if you're into that sort of thing.
Disclosure: I wrote the module.
One approach which I'm amazed no-one has mentioned yet is to use T4 Text Templates for code generation.
<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System" #>
<#@ output extension=".g.cs" #>
using System;
namespace Foo.Bar
{
public static partial class Constants
{
public static DateTime CompilationTimestampUtc { get { return new DateTime(<# Write(DateTime.UtcNow.Ticks.ToString()); #>L, DateTimeKind.Utc); } }
}
}
Pros:
Cons:
A different, PCL-friendly approach would be to use an MSBuild inline task to substitute the build time into a string that is returned by a property on the app. We are using this approach successfully in an app that has Xamarin.Forms, Xamarin.Android, and Xamarin.iOS projects.
EDIT:
Simplified by moving all of the logic into the SetBuildDate.targets
file, and using Regex
instead of simple string replace so that the file can be modified by each build without a "reset".
The MSBuild inline task definition (saved in a SetBuildDate.targets file local to the Xamarin.Forms project for this example):
<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>
Invoking the above inline task in the Xamarin.Forms csproj file in target BeforeBuild:
<!-- 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>
The FilePath
property is set to a BuildMetadata.cs
file in the Xamarin.Forms project that contains a simple class with a string property BuildDate
, into which the build time will be substituted:
public class BuildMetadata
{
public static string BuildDate => "This can be any arbitrary string";
}
Add this file BuildMetadata.cs
to project. It will be modified by every build, but in a manner that allows repeated builds (repeated replacements), so you may include or omit it in source control as desired.
For .NET Core projects, I adapted Postlagerkarte's answer to update the assembly Copyright field with the build date.
The following can be added directly to the first PropertyGroup
in the csproj:
<Copyright>Copyright © $([System.DateTime]::UtcNow.Year) Travis Troyer ($([System.DateTime]::UtcNow.ToString("s")))</Copyright>
Or paste the inner expression directly into the Copyright field in the Package section of the project properties in Visual Studio:
Copyright © $([System.DateTime]::UtcNow.Year) Travis Troyer ($([System.DateTime]::UtcNow.ToString("s")))
This can be a little confusing, because Visual Studio will evaluate the expression and display the current value in the window, but it will also update the project file appropriately behind the scenes.
You can plop the <Copyright>
element above into a Directory.Build.props
file in your solution root, and have it automatically applied to all projects within the directory, assuming each project does not supply its own Copyright value.
<Project>
<PropertyGroup>
<Copyright>Copyright © $([System.DateTime]::UtcNow.Year) Travis Troyer ($([System.DateTime]::UtcNow.ToString("s")))</Copyright>
</PropertyGroup>
</Project>
Directory.Build.props: Customize your build
The example expression will give you a copyright like this:
Copyright © 2018 Travis Troyer (2018-05-30T14:46:23)
You can view the copyright information from the file properties in Windows, or grab it at runtime:
var version = FileVersionInfo.GetVersionInfo(Assembly.GetEntryAssembly().Location);
Console.WriteLine(version.LegalCopyright);
I just added pre-build event command:
powershell -Command Get-Date -Format 'yyyy-MM-ddTHH:mm:sszzz' > Resources\BuildDateTime.txt
in the project properties to generate a resource file that is then easy to read from the code.