【问题标题】:How to display ClickOnce Version number on Windows Forms如何在 Windows 窗体上显示 ClickOnce 版本号
【发布时间】:2010-11-09 01:06:19
【问题描述】:

我有一个部署到两个不同位置的 Windows 窗体应用程序。

  • Intranet - ClickOnce
  • Internet - 通过 Windows 安装程序安装在 citrix 场中

我显示 ClickOnce 版本号为 click-once 部署版本ApplicationDeployment.IsNetworkDeployed

if (ApplicationDeployment.IsNetworkDeployed)
        return ApplicationDeployment.CurrentDeployment.CurrentVersion;

但是对于非点击应用程序,我不确定如何检索 clickonce 版本,除非我在程序集信息中硬编码版本号。

是否有自动检索非 clickonce 部署版本的 ClickOnce 版本号的方法?

【问题讨论】:

  • 我一直想知道微软是如何决定一个程序的两个版本有用的......然后没有办法将两者联系在一起。哎……
  • 真的很漂亮,虽然是无意的。 Cpg 的答案变得如此受欢迎,因为它回答的是人们在搜索引擎中输入自己的问题后访问此页面的问题,而 JaredPar 的答案已被标记为最佳答案,但仍然不是很受欢迎。

标签: c# .net deployment clickonce


【解决方案1】:
  1. 向您的项目添加对System.Deployment 的程序集引用。

  2. 在你的类文件中导入命名空间:

    VB.NET:

    Imports System.Deployment.Application
    

    C#:

    using System.Deployment.Application;
    
  3. CurrentVersion 属性中检索 ClickOnce 版本。

    您可以从ApplicationDeployment.CurrentDeployment.CurrentVersion 属性中获取当前版本。这将返回一个System.Version 对象。

    注意(来自 MSDN):

    如果有新的更新,CurrentVersion 将不同于 UpdatedVersion 已安装但您尚未调用Restart。如果部署 manifest配置为执行自动更新,可以对比 这两个值来确定您是否应该重新启动应用程序。

    注意:CurrentDeployment 静态属性仅在使用 ClickOnce 部署应用程序时有效。因此,在您访问此属性之前,您应该首先检查ApplicationDeployment.IsNetworkDeployed 属性。在调试环境中它总是会返回一个 false。

    VB.NET:

    Dim myVersion as Version
    
    If ApplicationDeployment.IsNetworkDeployed Then
       myVersion = ApplicationDeployment.CurrentDeployment.CurrentVersion
    End If
    

    C#:

    Version myVersion;
    
    if (ApplicationDeployment.IsNetworkDeployed)
       myVersion = ApplicationDeployment.CurrentDeployment.CurrentVersion;
    
  4. 使用Version 对象:

    从这里开始,您可以在标签中使用版本信息,例如在“关于”表单上,以这种方式:

    VB.NET:

    versionLabel.Text = String.Concat("ClickOnce published Version: v", myVersion)
    

    C#:

    versionLabel.Text = string.Concat("ClickOnce published Version: v", myVersion);
    

    Version 对象被格式化为四部分数字(major.minor.build.revision)。)

【讨论】:

  • 当它甚至没有回答原始问题时,它是如何被 [当前] 106 次投票的?最初的问题已经说它知道ApplicationDeployment.CurrentDeployment.CurrentVersion,而这个答案只是说要使用它。提问者非常清楚地想知道在作为非 ClickOnce 应用程序运行时如何获取版本。我知道如何做到这一点的唯一方法是在开发过程中手动解析 .csproj 的相对路径或使用“Microsoft.Build.BuildEngine.Project”。
【解决方案2】:

不,我不相信有办法。我相信 ClickOnce 信息来自清单,该清单仅在 ClickOnce 部署中可用。我认为对版本号进行硬编码是您的最佳选择。

【讨论】:

  • @JaredPar:谢谢,我实际上会尝试让问题保持开放状态,看看是否有人遇到过类似情况并能够提出一些解决方法。
  • +1 因为 cpg 的回答只是重申问题中的“解决方案”(尽管有更多细节)。
【解决方案3】:

每次发布​​新版本时,我都会简单地将主程序集的程序集版本与 CLickOnce 版本相同。然后当它作为非 clickonce 应用程序运行时,只需使用反射来获取程序集版本。

【讨论】:

  • 为什么不使用主程序集的版本作为 clickonce 运行呢?
  • 您必须更改 ClickOnce 版本,否则它不会作为更新安装。我通常会尽量保持程序集版本和 ClickOnce 版本相同,或者至少保持相同的次要版本,这取决于我们的发布版本将是什么。
  • 使用 AssemblyInfo 的问题是它不会自动保持程序集版本与 ClickOnce 版本相同。这将是团队中所有开发人员每次部署时都必须进行的手动更改。
【解决方案4】:

尝试线程验证:

if (ApplicationDeployment.IsNetworkDeployed)
{
    if (ApplicationDeployment.CurrentDeployment.CurrentVersion != ApplicationDeployment.CurrentDeployment.UpdatedVersion)
    {
        Application.ExitThread();
        Application.Restart();
    }
}

【讨论】:

    【解决方案5】:

    扩展 RobinDotNet 的解决方案:

    Protip:您可以在每次构建时从 .csproj 文件 MSBuild 配置中自动运行程序或脚本来为您执行此操作。我为我当前维护的一个 Web 应用程序执行此操作,执行 Cygwin bash shell 脚本来执行一些版本控制 h4x 以从 Git 历史计算版本号,然后预处理编译到构建输出中的程序集信息源文件。

    可以做类似的事情来解析项目文件中的 ClickOnce 版本号,即 Project.PropertyGroup.ApplicationRevisionProject.PropertyGroup.ApplicationVersion(虽然我不知道版本字符串的含义,但你可以猜测直到它中断然后修复它)并将该版本信息插入到程序集信息中。

    我不知道 ClickOnce 版本何时更新,但可能是在构建过程之后,因此您可能需要修改此解决方案以获取编译的新数字。 我猜总是有/*h4x*/ +1

    我使用 Cygwin 是因为 *nix 脚本编写比 Windows 好得多,而且解释代码为您省去了 在构建之前构建预构建程序的麻烦,但是您可以使用任何您想要的技术来编写程序想要(包括 C#/.NET)。预处理器的命令行进入PreBuildEvent

    <PropertyGroup>
      <PreBuildEvent>
        $(CYGWIN_ROOT)bin\bash.exe --login -c refresh-version
      </PreBuildEvent>
    </PropertyGroup>
    

    正如您想象的那样,这发生在构建阶段之前,因此您可以在编译之前有效地预处理您的源代码。我不想自动编辑Properties\AssemblyInfo.cs 文件,所以为了安全起见,我所做的是创建一个Properties\VersionInfo.base.cs 文件,其中包含带有版本信息的类的文本模板,并在项目中标记为BuildAction=None设置,使其不与项目一起编译:

    using System.Reflection;
    using EngiCan.Common.Properties;
    
    [assembly: AssemblyVersion("0.$REVNUM_DIV(100)$.$REVNUM_MOD(100)$.$DIRTY$")]
    [assembly: AssemblyRevisionIdentifier("$REVID$")]
    

    (为了简单/复杂,使用了一种非常肮脏、穷人的占位符语法,类似于 Windows 的环境变量,并添加了一些额外的 h4x)

    AssemblyRevisionIdentifierAttribute 是我创建的用于保存 Git SHA1 的自定义属性,因为它对开发人员来说比 a.b.c.d 更有意义。

    我的refresh-version 程序然后将该文件复制到Properties\VersionInfo.cs,然后替换它已经计算/解析的版本信息(我使用sed(1) 进行替换,这是使用Cygwin 的另一个好处)。 Properties\VersionInfo.cs 已编译到程序中。该文件一开始可能是空的,您应该通过版本控制系统忽略它,因为它会自动更改,并且生成它的信息已经存储在其他地方。

    【讨论】:

      【解决方案6】:

      硬代码,或... 在数据库中跟踪您的版本(文件、程序集、部署)。使用您的程序集调用数据库并获取部署版本。

      这假设您正在以一种合乎逻辑的方式递增您的版本,以便每个版本类型都有关系。对于这样一个小问题,需要做很多工作。我个人会选择 Jared 的解决方案;虽然我讨厌硬编码任何东西。

      【讨论】:

      • @Coov:“我讨厌硬编码任何东西”这正是我在考虑是否有办法解决这个问题的原因。我没有想过数据库来跟踪版本号。感谢您提供解决此问题的另一种方法。
      • 将它存储在数据库中对我来说毫无意义。它类似于硬编码。为什么不使用每次发布都会增加的清单?
      【解决方案7】:

      使用构建组件,您可以从项目文件中读取单击一次的版本,并将其自动写入程序集信息中,以便两者同步。

      【讨论】:

      • 你有这方面的例子吗?
      【解决方案8】:

      三年后没关系,但我最终只是用 xml 阅读器解析清单文件。

      【讨论】:

      • 为什么不用cpg的解决方案?
      【解决方案9】:

      进行线程验证,插入硬代码...

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-11-22
        • 2023-03-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-08-13
        相关资源
        最近更新 更多