24

在我的 Defines.wxi 中,我有:

<?define MajorVersion="1" ?>
<?define MinorVersion="08" ?>
<?define BuildVersion="11" ?>

在我的 MyProject.Setup.wixproj 我有:

<OutputName>MyProject</OutputName>
<OutputType>Package</OutputType>

是否可以以某种方式在文件名中包含版本变量,以便我的文件可以命名为 MyProject.1.08.11.msi?

这不起作用(没有定义这样的变量):

<OutputName>MyProject-$(MajorVersion)</OutputName>
<OutputType>Package</OutputType>

这不起作用(没有定义这样的变量):

<Target Name="AfterBuild" Condition="'$(Configuration)' == 'Release'">
    <Copy SourceFiles="$(OutputPath)$(OutputName).msi" DestinationFiles="C:\$(OutputName)-$(MajorVersion).msi" />
</Target>

我似乎很清楚 $(MajorVersion) 不是从 Defines.wxi 文件中获取定义的正确方法。什么是?


更新

我试图把它放在 MyProject.Setup.wixproj 中:

<InstallerMajorVersion>7</InstallerMajorVersion>
<InstallerMinorVersion>7</InstallerMinorVersion>
<InstallerBuildNumber>7</InstallerBuildNumber>

...

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
    <OutputPath>bin\$(Configuration)\</OutputPath>
    <IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
    <DefineConstants>PrebuildPath=..\..\obj\prebuild\web\;InstallerMajorVersion=$(InstallerMajorVersion);InstallerMinorVersion=$(InstallerMinorVersion);InstallerBuildNumber=$(InstallerBuildNumber)</DefineConstants>
</PropertyGroup>

这在Defines.wxi中:

<?define MajorVersion="$(var.InstallerMajorVersion)" ?>
<?define MinorVersion="$(var.InstallerMinorVersion)" ?>
<?define BuildVersion="$(var.InstallerBuildNumber)" ?>
<?define Revision="0" ?>
<?define VersionNumber="$(var.InstallerMajorVersion).$(var.InstallerMinorVersion).$(var.InstallerBuildNumber)" ?>

也没有用。收到以下错误消息:

  • Product/@Version 属性的值“..”不是有效版本。合法版本值应类似于“xxxx”,其中 x 是 0 到 65534 之间的整数。
  • 未找到 Product/@Version 属性;这是必需的。
4

7 回答 7

15

这就是我最终得到的,它有效!

安装程序.版本.proj

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <PropertyGroup>
        <InstallerMajorVersion>55</InstallerMajorVersion>
        <InstallerMinorVersion>66</InstallerMinorVersion>
    <InstallerBuildVersion>$(BuildNumber)</InstallerBuildVersion>
        <InstallerBuildVersion Condition="$(InstallerBuildVersion) == ''">0</InstallerBuildVersion>
  </PropertyGroup>
</Project>

MyProject.Setup.wixproj

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="Setup.Version.proj" />
  <PropertyGroup>
    <OutputName>MyProject_$(InstallerMajorVersion)_$(InstallerMinorVersion)_$(InstallerBuildVersion)</OutputName>
    <OutputType>Package</OutputType>
    <DefineConstants>InstallerMajorVersion=$(InstallerMajorVersion);InstallerMinorVersion=$(InstallerMinorVersion);InstallerBuildVersion=$(InstallerBuildVersion)</DefineConstants>
    ...

定义.wxi

<?define MajorVersion="$(var.InstallerMajorVersion)" ?>
<?define MinorVersion="$(var.InstallerMinorVersion)" ?>
<?define BuildVersion="$(var.InstallerBuildVersion)" ?>
于 2012-09-13T14:55:27.777 回答
14

在未来的 WiX 版本中应该简化这个常见的任务!

这个解决方案结合了@Wimmel 和这篇文章。它从目标 .exe 中提取版本,否则不在文件中存储版本号;它不会在构建后重命名输出文件。但是,有必要更新属性 ProjectDefineConstants,从中派生蜡烛参数(在 wix.targets 中)。否则,仅更新 TargetPath 属性不会更改烛台.exe 的输入。

*.wi​​xproj:

<Import Project="$(WixTargetsPath)" />
<Target Name="BeforeBuild">
  <!-- Read the version from the to-be-installed .exe -->
  <GetAssemblyIdentity AssemblyFiles="path.to.primary.exe">
    <Output TaskParameter="Assemblies" ItemName="AsmInfo" />
  </GetAssemblyIdentity>

  <!-- Create the MSBuild property $(VersionNumber) -->
  <CreateProperty Value="%(AsmInfo.Version)">
    <Output TaskParameter="Value" PropertyName="VersionNumber" />
  </CreateProperty>

  <!-- Create the WiX preprocessor variable $(var.VersionNumber) -->
  <CreateProperty Value="$(DefineConstants);VersionNumber=$(VersionNumber)">
    <Output TaskParameter="Value" PropertyName="DefineConstants" />
  </CreateProperty>

  <!-- Update the MSBuild properties $(TargetName), etc. -->
  <CreateProperty Value="$(SolutionName)-$(Platform)-$(VersionNumber)">
    <Output TaskParameter="Value" PropertyName="TargetName" />
  </CreateProperty>
  <CreateProperty Value="$(TargetName)$(TargetExt)">
    <Output TaskParameter="Value" PropertyName="TargetFileName" />
  </CreateProperty>
  <CreateProperty Value="$(TargetName)$(TargetPdbExt)">
    <Output TaskParameter="Value" PropertyName="TargetPdbName" />
  </CreateProperty>
  <CreateProperty Value="$(TargetDir)$(TargetFileName)">
    <Output TaskParameter="Value" PropertyName="TargetPath" />
  </CreateProperty>
  <CreateProperty Value="$(TargetPdbDir)$(TargetPdbName)">
    <Output TaskParameter="Value" PropertyName="TargetPdbPath" />
  </CreateProperty>

  <!-- Update the MSBuild property from which candle.exe args are derived -->
  <CreateProperty Value="
    Configuration=$(ConfigurationName);
    OutDir=$(OutDir);
    Platform=$(PlatformName);
    ProjectDir=$(ProjectDir);
    ProjectExt=$(ProjectExt);
    ProjectFileName=$(ProjectFileName);
    ProjectName=$(ProjectName);
    ProjectPath=$(ProjectPath);
    TargetDir=$(TargetDir);
    TargetExt=$(TargetExt);
    TargetFileName=$(TargetFileName);
    TargetName=$(TargetName);
    TargetPath=$(TargetPath);
  ">
    <Output TaskParameter="Value" PropertyName="ProjectDefineConstants" />
  </CreateProperty>
</Target>

*.wxs

<Product Id="*" Version="$(var.VersionNumber)" ... >
  ...
</Product>
于 2013-01-17T08:38:18.520 回答
9

在您的 .wixproj 文件中。</Project>在标记之前添加以下部分。

<!-- rename the output msi with Version number -->
  <Target Name="AfterBuild">
    <GetAssemblyIdentity AssemblyFiles="[Path of the main assembly with the assembly version number you want to use]">
      <Output TaskParameter="Assemblies" ItemName="AssemblyVersion"/>
    </GetAssemblyIdentity>
    <Copy SourceFiles=".\bin\$(Configuration)\$(OutputName).msi" DestinationFiles=".\bin\$(Configuration)\$(OutputName)_%(AssemblyVersion.Version).msi" />
    <Delete Files=".\bin\$(Configuration)\$(OutputName).msi" />
  </Target>

这对我有用。

于 2013-01-16T10:37:36.073 回答
5

无法从 .wixproj 文件中读取 .wxi 文件。所以你必须使用另一种方式来指定版本。我可以举一个例子,我从安装程序中包含的程序集中读取版本,并使用该版本重命名 msi;

在编辑器中打开 .wixproj 文件并添加一个ReadVersion目标:

  <Target Name="ReadVersion">
    <GetAssemblyIdentity AssemblyFiles="bin\program.exe">
      <Output TaskParameter="Assemblies" ItemName="MyAssemblyIdentities" />
    </GetAssemblyIdentity>
    <Message Text="AssemblyVersion = %(MyAssemblyIdentities.Version)" />
    <CreateProperty Value="$(TargetName) %(MyAssemblyIdentities.Version)">
      <Output TaskParameter="Value" PropertyName="TargetName" />
    </CreateProperty>
    <CreateProperty Value="$(TargetName)$(TargetExt)">
      <Output TaskParameter="Value" PropertyName="TargetFileName" />
    </CreateProperty>
    <CreateProperty Value="$(OutDir)$(TargetFileName)">
      <Output TaskParameter="Value" PropertyName="TargetPath" />
    </CreateProperty>
  </Target>

这将从 中读取版本bin\program.exe,将其显示以进行调试,并更改 TargetName、TargetFileName 和 TargetPath。

在包含 的行之后<Import Project="$(WixTargetsPath)" />,添加以下内容以将此目标注入到构建过程中:

  <PropertyGroup>
    <BuildDependsOn>ReadVersion;$(BuildDependsOn)</BuildDependsOn>
  </PropertyGroup>
于 2012-09-07T18:49:27.843 回答
4

一种方法是在您的 MSBuild 脚本中定义变量,并让它在构建时更新 Defines.wxi,如本例所示

在您的 MSBuild 脚本中,您可以按如下方式定义版本属性:

  <PropertyGroup>
    <MajorVersion>1</MajorVersion>
    <MinorVersion>08</MinorVersion>
    <BuildVersion>11</BuildVersion>
    <WixConfigPath>.\Defines.wxi</WixConfigPath>

    <_VariableDefinitions>
      <Root>
        <VariableDefinition Name="MajorVersion" NewValue="$(MajorVersion)" />
        <VariableDefinition Name="MinorVersion" NewValue="$(MinorVersion)" />
        <VariableDefinition Name="BuildVersion" NewValue="$(BuildVersion)" />
      </Root>
    </_VariableDefinitions>
  </PropertyGroup>

  <Target Name="UpdateWixVars">
    <WixVarSubstitution SourceFile="$(WixConfigPath)" VariableDefinitions="$(_VariableDefinitions)"/>
  </Target>

然后运行 ​​UpdateWixVars 目标将使用 MSBuild 项目中指定的版本号更新 Defines.wxi 中的版本号。

请注意,我无法使用此自定义构建任务找到实际编译的 dll,因此我必须通过以下方式创建它:

  1. 从这里下载源代码。构建它并将文件命名为 Tranxition.BuildTasks.dll。
  2. 添加对构建任务的引用,如下所示:

    <UsingTask TaskName="WixVarSubstitution"
         AssemblyFile="$(MSBuildExtensionsPath)\Tranxition\Tranxition.BuildTasks.dll"/>
    
于 2012-09-07T15:29:39.177 回答
2

您可以通过实现以下两个答案来无缝完成此任务:

其他答案太复杂了!

PS:如果你想去掉第四位,按照语义版本控制,你可以这样做:

<Target Name="AfterBuild">
    <GetAssemblyIdentity AssemblyFiles="..\Path\To\MyProject\bin\$(Platform)\$(Configuration)\MyProject.dll">
        <Output TaskParameter="Assemblies" ItemName="AssemblyInfo" />
    </GetAssemblyIdentity>
    <PropertyGroup>
        <In>%(AssemblyInfo.Version)</In>
        <Pattern>^(\d+.\d+.\d+)</Pattern>
        <AssemblyVersion>$([System.Text.RegularExpressions.Regex]::Match($(In), $(Pattern)))</AssemblyVersion>
    </PropertyGroup>
    <Move SourceFiles="bin\$(Platform)\$(Configuration)\MyProject.msi" DestinationFiles="bin\$(Platform)\$(Configuration)\CodeGenerator-$(AssemblyVersion).$(Platform).msi" />
</Target>

这将创建一个名为的 MSI,例如MyProject-1.2.3.x64.msi. 有关更多信息,请参阅此答案

于 2016-03-02T19:04:50.190 回答
0

这是 wixproj 文件的完整示例,您可以在其中设置 UI 中的版本号并使用它来修改输出 msi 文件名。

在 Visual Studio(例如 2015)中:

  • 在项目属性窗口的“定义预处理器变量”中定义版本号。我在这个例子中输入了 VersionNumber=1.14;
  • 在解决方案资源管理器中卸载您的项目;
  • 在解决方案资源管理器中右键单击您的项目,然后选择编辑 yourproject.wixproj 文件;
  • 在 Target Name="BeforeBuild" 元素中添加代码,如下所示。

    <?xml version="1.0" encoding="utf-8"?>
    <Project ToolsVersion="4.0" DefaultTargets="Build" InitialTargets="EnsureWixToolsetInstalled" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
      <PropertyGroup>
        <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
        <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
        <ProductVersion>3.10</ProductVersion>
        <ProjectGuid>PROJECT-GUID</ProjectGuid>
        <SchemaVersion>2.0</SchemaVersion>
        <OutputName>my project</OutputName>
        <OutputType>Package</OutputType>
      </PropertyGroup>
      <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
        <OutputPath>bin\$(Configuration)\</OutputPath>
        <IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
        <!-- These constants can be set in the UI -->
        <DefineConstants>VersionNumber=1.14</DefineConstants>
      </PropertyGroup>
      <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
        <OutputPath>bin\$(Configuration)\</OutputPath>
        <IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
        <DefineConstants>VersionNumber=1.14</DefineConstants>
      </PropertyGroup>
      <ItemGroup>
        <Compile Include="Product.wxs" />
      </ItemGroup>
      <ItemGroup>
        <WixExtension Include="WixUIExtension">
          <HintPath>$(WixExtDir)\WixUIExtension.dll</HintPath>
          <Name>WixUIExtension</Name>
        </WixExtension>
      </ItemGroup>
      <Import Project="$(WixTargetsPath)" Condition=" '$(WixTargetsPath)' != '' " />
      <Import Project="$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets" Condition=" '$(WixTargetsPath)' == '' AND Exists('$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets') " />
    
      <Target Name="BeforeBuild">
        <!-- This extracts the version number from a setting in the UI -->
        <!-- This method comes from: geekswithblogs.net/alexhildyard/archive/2013/03/09/passing-data-between-msbuild-and-wix.aspx -->
        <ItemGroup>
          <DefineConstantsKVPairs Include="$(DefineConstants)" />
        </ItemGroup>
        <!-- Evaluate each key/value pair with task batching, then make a conditional assignment -->
        <PropertyGroup>
          <VersionNumber Condition="$([System.String]::new('%(DefineConstantsKVPairs.Identity)').Contains('VersionNumber='))">$([System.String]::new('%(DefineConstantsKVPairs.Identity)').Split('=')[1])</VersionNumber>
        </PropertyGroup>
    
        <CreateProperty Value="$(OutputName)-$(VersionNumber)">
          <Output TaskParameter="Value" PropertyName="TargetName" />
        </CreateProperty>
        <CreateProperty Value="$(TargetName)$(TargetExt)">
          <Output TaskParameter="Value" PropertyName="TargetFileName" />
        </CreateProperty>
        <CreateProperty Value="$(TargetDir)$(TargetFileName)">
          <Output TaskParameter="Value" PropertyName="TargetPath" />
        </CreateProperty>
      </Target>
    </Project>
    
于 2017-07-24T06:15:27.863 回答