在我的代码中,我需要 Xamarin 程序集构建日期。在 Windows 上我可以使用 linker time stamp 。然而在 iOS 上这不起作用。我猜它在 OS X 上也不起作用,因为可移植可执行文件头是 Windows 特有的。
还有一个选项可以嵌入带有日期的资源,但是我想避免在此特定项目中使用资源。
有没有办法找到适用于 iOS、Android 和 OS X 的 Xamarin 程序集构建日期?
最佳答案
一种方法是使用 MSBuild 任务将构建时间替换为应用程序属性返回的字符串。我们在具有 Xamarin.Forms、Xamarin.Android 和 Xamarin.iOS 项目的应用中成功使用了此方法。
如果使用 msbuild,这可以是 MSBuild 内联任务,而在 Mac 上使用 xbuild,则需要是为 Mono 编译的 MSBuild 自定义任务。
编辑:
通过将所有逻辑移至构建任务中并使用 Regex
而不是简单的字符串替换来进行简化,以便每次构建都可以修改文件而无需“重置”。
MSBuild 内联任务定义(在本示例中保存在 Xamarin.Forms 项目本地的 SetBuildDate.targets 文件中):
<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>
编辑:
添加了 MSBuild Exec 步骤以删除只读属性。一定会喜欢 TFS。
在目标 BeforeBuild 的 Xamarin.Forms csproj 文件中调用 MSBuild 任务(内联或编译,内联方法针对 xbuild 进行注释):
<!-- 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" />-->
<UsingTask AssemblyFile="$(MSBuildProjectDirectory)\BI.Framework.BuildExtensions.dll" TaskName="Some.Framework.BuildExtensions.BuildDateTask" />
<Target Name="BeforeBuild">
<Exec Command="attrib $(MSBuildProjectDirectory)\BuildMetadata.cs -r" />
<!--<SetBuildDate FilePath="$(MSBuildProjectDirectory)\BuildMetadata.cs" />-->
<BuildDateTask FilePath="$(MSBuildProjectDirectory)\BuildMetadata.cs" />
</Target>
FilePath
属性设置为 Xamarin.Forms 项目中的 BuildMetadata.cs
文件,该文件包含一个带有字符串属性 BuildDate
的简单类>,构建时间将被替换为:
public class BuildMetadata
{
public static string BuildDate => "This can be any arbitrary string";
}
将此文件 BuildMetadata.cs
添加到项目中。每次构建都会对其进行修改,但修改方式允许重复构建(重复替换),因此您可以根据需要在源代码管理中包含或省略它。
添加:
下面是一个自定义 MSBuild 任务,用于替换在 Mac 上使用 xbuild
进行构建时的 MSBuild 内联任务:
using System;
using System.IO;
using System.Text.RegularExpressions;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
namespace Some.Framework.BuildExtensions
{
public class BuildDateTask : Task
{
#region Methods
/// <summary>
/// Called automatically when the task is run.
/// </summary>
/// <returns><c>true</c>for task success, <c>false</c> otherwise.</returns>
public override bool Execute()
{
const string pattern = @"BuildDate => ""([^""]*)""";
var now = DateTime.UtcNow;
var buildDate = now.ToString("F");
var replacement = $"BuildDate => \"{buildDate}\"";
var content = File.ReadAllText(FilePath);
var rgx = new Regex(pattern);
content = rgx.Replace(content, replacement);
File.WriteAllText(FilePath, content);
File.SetLastWriteTimeUtc(FilePath, now);
return true;
}
#endregion Methods
#region Properties
[Required]
public string FilePath { get; set; }
#endregion Properties
}
}
通过 xbuild 为 Release 构建此自定义任务,然后将输出自定义任务 dll 复制到要为其设置构建日期的项目的项目目录。
关于xamarin - 获取 iOS、Android 和 OS X 上的 Xamarin 程序集构建日期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37119859/