如何在.NET ClickOnce应用程序中将发布版本与程序集版本同步?

41
在我的 C# ClickOnce 应用程序中,项目的“属性”->“发布”选项卡中有一个自动递增的发布版本。我想在我的菜单“帮助”->“关于”框中显示该版本号,但是我正在使用的代码似乎访问的是程序集版本,而这个版本与发布版本不同。
可以在项目的“属性”->“应用程序”->“程序集信息”对话框中手动更改程序集版本。因此,现在每次发布之前我都将发布版本复制到程序集版本中,以便我的对话框显示当前应用程序的版本。一定有更好的方法来做到这一点。
我真正想做的就是拥有一个准确、自动更新且可访问的代码版本号。
以下是我用来访问程序集版本号的代码:
public string AssemblyVersion
{
    get
    {
        return Assembly.GetExecutingAssembly().GetName().Version.ToString();
    }
}
另一种选择是找到访问发布版本的代码。
6个回答

23

sylvanaar的最后一行代码看起来是比较好的方案。但需要注意的是,该方法只适用于应用程序的已部署版本。如果想要进行调试,可能需要使用以下方法:

    static internal string GetVersion()
    {
        if (ApplicationDeployment.IsNetworkDeployed)
        {
            return ApplicationDeployment.CurrentDeployment.CurrentVersion.ToString();
        }

        return "Debug";
    }

非常感谢 - 这是最简单的方法,而且它似乎运行良好! - Randy Gamage
4
不过并不理想,因为当你右键单击一个程序集并查看属性时,显示的版本仍然是AssemblyVersion。 - Roman Starkov
注意:ApplicationDeployment.IsNetworkDeployed 会导致抛出第一次机会异常。这可能会干扰调试等操作。 - Peter Mortensen
2
使用 if (!Debugger.IsAttached && ApplicationDeployment.*) {...} 可以避免在从 VisualStudio 调试 ClickOnce 应用程序时出现第一次机会异常。 - HodlDwon
1
添加 if (ApplicationDeployment.IsNetworkDeployed) 似乎可以防止任何调试异常,这可能是在 VS 2015 中新增的功能。我只是想分享一下以供讨论和/或帮助他人。如果没有它,应用程序每次都会抛出异常。为了保险起见,添加 try catch 也许不是一个坏主意。 - Anthony Mason

10

我修改了我的 .csproj 文件以更新程序集版本。我为此创建了一个名为“公共发布”的配置,但这并不是必须的。

  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
  <!-- 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.
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target>
  -->
  <PropertyGroup Condition="'$(BuildingInsideVisualStudio)' == 'true'">
    <MSBuildCommunityTasksPath>$(SolutionDir)Tools\MSBuildCommunityTasks</MSBuildCommunityTasksPath>
  </PropertyGroup>
  <!-- Required Import to use MSBuild Community Tasks -->
  <Import Project="$(SolutionDir)Tools\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets" Condition="'$(BuildingInsideVisualStudio)' == 'true'" />
  <Target Name="BeforeCompile" Condition="'$(BuildingInsideVisualStudio)|$(Configuration)' == 'true|PublicRelease'">
    <FormatVersion Version="$(ApplicationVersion)" Revision="$(ApplicationRevision)">
      <Output TaskParameter="OutputVersion" PropertyName="AssemblyVersionToUse" />
    </FormatVersion>
    <AssemblyInfo CodeLanguage="CS" OutputFile="$(ProjectDir)Properties\VersionInfo.cs" AssemblyVersion="$(AssemblyVersionToUse)" AssemblyFileVersion="$(AssemblyVersionToUse)" />
  </Target>

发布的版本可能是:

ApplicationDeployment.CurrentDeployment.CurrentVersion

7
我愿意对Sylvanaar的答案进行补充说明,因为其中一些实现细节对我来说并不明显。所以:
  1. 手动安装社区构建任务,可以在以下网址找到:https://github.com/loresoft/msbuildtasks/releases 注意:如果您清除了软件包,则不要通过nuget进行安装,因为在生成文件中msbuildtasks被引用为任务,在还原软件包之前生成将失败。我将它们放在与解决方案文件相邻的文件夹中,名为.build

  2. 在项目属性文件夹中添加一个完全为空的文件,名为VersionInfo.cs

3 如果AssemblyInfo.cs文件中存在以下行,请将其删除

[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("1.0.*")]

4 修改你的csproj文件

  <!-- Include the build rules for a C# project. -->
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

  <!--INSERT STARTS HERE-->
  <!--note the use of .build directory-->
  <PropertyGroup Condition="'$(BuildingInsideVisualStudio)' == 'true'">
    <MSBuildCommunityTasksPath>$(SolutionDir)\.build\MSBuildCommunityTasks</MSBuildCommunityTasksPath>
  </PropertyGroup>
  <!-- Required Import to use MSBuild Community Tasks -->
  <Import Project="$(SolutionDir)\.build\MSBuild.Community.Tasks.targets" Condition="'$(BuildingInsideVisualStudio)' == 'true'" />
  <Target Name="BeforeCompile" Condition="'$(BuildingInsideVisualStudio)|$(Configuration)' == 'true|Release'">
    <FormatVersion Version="$(ApplicationVersion)" Revision="$(ApplicationRevision)">
      <Output TaskParameter="OutputVersion" PropertyName="AssemblyVersionToUse" />
    </FormatVersion>
    <AssemblyInfo CodeLanguage="CS" OutputFile="$(ProjectDir)Properties\VersionInfo.cs" AssemblyVersion="$(AssemblyVersionToUse)" AssemblyFileVersion="$(AssemblyVersionToUse)" />
  </Target>

使用以下类似的方法访问版本文本:

public string Version()
{
    Version version = null;

    if (ApplicationDeployment.IsNetworkDeployed)
    {
        version = ApplicationDeployment.CurrentDeployment.CurrentVersion;
    }
    else
    {
        version = typeof(ThisAddIn).Assembly.GetName().Version;
    }

    return version.ToString();
}

3
我采用了另一种方法,使用通配符来表示我的程序集版本号 - 1.0.* - 这样Visual Studio/MSBuild会自动生成一个版本号:
// AssemblyInfo.cs    
[assembly: AssemblyVersion("1.0.*")]

然后我在ClickOnce项目中添加了以下AfterCompile目标,将同步PublishVersion与程序集版本进行分配:

<Target Name="AfterCompile">
    <GetAssemblyIdentity AssemblyFiles="$(IntermediateOutputPath)$(TargetFileName)">
      <Output TaskParameter="Assemblies" ItemName="TargetAssemblyIdentity" />
    </GetAssemblyIdentity>
    <PropertyGroup>
      <PublishVersion>%(TargetAssemblyIdentity.Version)</PublishVersion>
    </PropertyGroup>
</Target>

1
我按照这个方法操作,但是更改了应用程序版本后,似乎可以工作,但网站显示的版本号不正确。 - Brian Hanf

3

我修改了sylvanaar的解决方案以适用于VB:

- Microsoft.VisualBasic.targets instead of Microsoft.CSharp.targets
- CodeLanguage="VB" instead of CodeLanguage="CS" 
- AssemblyInfo.vb instead of VersionInfo.cs

路径差异:

- $(SolutionDir).build instead of $(SolutionDir)Tools\MSBuildCommunityTasks
- $(ProjectDir)AssemblyInfo.vb instead of $(ProjectDir)Properties\VersionInfo.cs

并删去条件:

- Condition="'$(BuildingInsideVisualStudio)' == 'true'"
- Condition="'$(BuildingInsideVisualStudio)|$(Configuration)' == 'true|PublicRelease'"

我还将公司和产品与 ClickOnce 的 PublisherName 和 ProductName 同步,并根据当前日期生成了版权信息。
- AssemblyCompany="$(PublisherName)"
- AssemblyProduct="$(ProductName)" 
- AssemblyCopyright=$([System.DateTime]::Now.ToString(`yyyy`)) $(PublisherName)"

我最终添加了这个到我的vbproj文件中。它需要先安装MSBuildTasks NuGet包:

  <Import Project="$(MSBuildBinPath)\Microsoft.VisualBasic.targets" />
  <PropertyGroup Condition="'$(BuildingInsideVisualStudio)' == 'true'">
    <MSBuildCommunityTasksPath>$(SolutionDir).build</MSBuildCommunityTasksPath>
  </PropertyGroup>
  <Import Project="$(MSBuildCommunityTasksPath)\MSBuild.Community.Tasks.Targets" Condition="'$(BuildingInsideVisualStudio)' == 'true'" />
  <Target Name="BeforeCompile">  
    <FormatVersion Version="$(ApplicationVersion)" Revision="$(ApplicationRevision)">
      <Output TaskParameter="OutputVersion" PropertyName="AssemblyVersionToUse" />
    </FormatVersion>
    <AssemblyInfo CodeLanguage="VB" OutputFile="$(ProjectDir)AssemblyInfo.vb" AssemblyVersion="$(AssemblyVersionToUse)" AssemblyFileVersion="$(AssemblyVersionToUse)" AssemblyCompany="$(PublisherName)" AssemblyProduct="$(ProductName)" AssemblyCopyright=$([System.DateTime]::Now.ToString(`yyyy`)) $(PublisherName)"/>
  </Target>

我不确定在项目文件中位置的重要性,但我将其添加到我的项目文件末尾,就在此之前:

</Project>

0
其他解决方案将提供来自AssemblyInfo.cs的书面文本(例如,“2.5.*”)或适用于早期的 .net5 运行时。
为了从MainWindow.xaml代码后台获取不确定性的图像运行时版本(带有构建等),请执行以下操作:
private string GetVersion() =>
   typeof(MainWindow).Assembly.GetName().Version.ToString();

[1] 确保您处于非确定模式下(对于 .net5+),在项目文件中:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <Deterministic>false</Deterministic>

示例:

在 AssemblyInfo.cs 文件中,给定以下行:

[assembly: AssemblyVersion("4.1.*")]

ImageRuntimeVersion 将会是:

v4.1.3034.8779


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接