我使用每次构建时重新生成的包含文件中的 WiX 变量。
由于我的项目是 .wixproj (MSBuild/Visual Studio),因此我只是将版本提取和格式设置为自定义的内联 MSBuild 任务,并在 BeforeBuild 目标中调用它。
在下面的示例中,我获取了产品主组件的组件版本。您可以将其编码为您想要的任何版本。
使用 WiX Include 和变量
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<?include ProductVersion.wxi?>
<Product Version="$(var.ProductVersion)" …>
…
</Wix>
示例 ProductVersion.wxi
<Include>
<?define ProductVersion=1.0.38549?>
</Include>
我建议在项目中包含 .wxi 文件,以便它在解决方案视图中可见。而且,由于它已生成,我建议将其从源代码管理中排除。
编辑WixProj
.wixproj 既是 Visual Studio 项目文件,也是 MSBuild 项目文件。要在 Visual Studio 中编辑 Visual Studio 项目文件,请选择教程或扩展 https://www.google.com/search?q=edit+visual+studio+project+file.
构建目标之前
MSBuild 系统(包括 WiX 的系统)提供 BeforeBuild 和 AfterBuild 目标,如 .wixproj 注释中所述。
只需将目标从注释中拉出并添加任务调用即可。
<Target Name="BeforeBuild">
<GenerateProductVersion AssemblyPath='../wherever/whatever.exe' />
</Target>
MSBuild 内联任务
任务代码可以位于其自己的 MSBuild 文件甚至 DLL 中以供重用。或者,对于脚本方法,它可以是内联的。
此任务分为 3 个部分:
- 文件路径参数(因为它会因项目而异)
- 提取(带日志记录)
- 包含生成(项目文件夹中的硬编码名称,因为它不需要改变)
.
<UsingTask TaskName="GenerateProductVersion" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
<ParameterGroup>
<AssemblyPath ParameterType="System.String" Required="true" />
</ParameterGroup>
<Task>
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
<Using Namespace="System" />
<Using Namespace="System.Xml.Linq" />
<Using Namespace="System.Reflection" />
<Code Type="Fragment" Language="cs"><![CDATA[
var assemblyVersion = AssemblyName.GetAssemblyName(AssemblyPath).Version;
var productVersion = String.Format("{0}.{1}.{2}", assemblyVersion.Major, assemblyVersion.Minor, assemblyVersion.Revision);
Log.LogMessage(MessageImportance.High, "ProductVersion=" + productVersion + " extracted from assembly version of " + AssemblyPath);
new XDocument(
new XElement("Include",
new XProcessingInstruction("define", "ProductVersion=" + productVersion)))
.Save("ProductVersion.wxi");
]]></Code>
</Task>
</UsingTask>
使 EXE 路径更加可见
所有这些都在项目文件中隐藏得很好。许多项目设计者都有一个“构建”选项卡,允许在构建中输入名称-值对。这提供了一种从 XML 中向上提升路径的机制。
<Target Name="BeforeBuild">
<GenerateProductVersion AssemblyPath='$([System.Text.RegularExpressions.Regex]::Match(";$(DefineConstants);", ";VersionExtractionPath=(?<path>.*?);").Groups["path"].Value)' />
</Target>