我目前有一个应用程序显示构建号在其标题窗口。这很好,除了它对大多数用户没有任何意义,他们想知道他们是否有最新的版本-他们倾向于将其称为“上周四的”而不是1.0.8.4321版本。
计划是把构建日期放在那里,例如“App构建于21/10/2009”。
我正在努力寻找一种程序化的方法,将构建日期作为文本字符串提取出来,以便像这样使用。
对于版本号,我使用:
Assembly.GetExecutingAssembly().GetName().Version.ToString()
在定义了这些是怎么来的之后。
我希望编译日期(和时间,为了加分)也像这样。
非常感谢这里的指示(如果合适的话,借口双关语),或者更整洁的解决方案……
关于从程序集PE头的字节中提取构建日期/版本信息的技术,Microsoft已经从Visual Studio 15.4开始更改了默认的构建参数。新的默认包含确定性编译,这使得有效的时间戳和自动递增的版本号成为过去式。时间戳字段仍然存在,但它被一个永久值填充,该值是某个东西的哈希值,而不是任何构建时间的指示。
这里有一些详细的背景
对于那些将有用的时间戳优先于确定性编译的人来说,有一种方法可以覆盖新的默认值。您可以在感兴趣的程序集的.csproj文件中包含一个标记,如下所示:
<PropertyGroup>
...
<Deterministic>false</Deterministic>
</PropertyGroup>
Update:
I endorse the T4 text template solution described in another answer here. I used it to solve my issue cleanly without losing the benefit of deterministic compilation. One caution about it is that Visual Studio only runs the T4 compiler when the .tt file is saved, not at build time. This can be awkward if you exclude the .cs result from source control (since you expect it to be generated) and another developer checks out the code. Without resaving, they won't have the .cs file. There is a package on nuget (I think called AutoT4) that makes T4 compilation part of every build. I have not yet confronted the solution to this during production deployment, but I expect something similar to make it right.
另一种不同的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添加到项目中。它将在每次构建时被修改,但是以一种允许重复构建的方式(重复替换),因此您可以根据需要在源代码控制中包含或省略它。