【问题标题】:Restart WPF application after click-once update (start the new version)单击一次更新后重新启动 WPF 应用程序(启动新版本)
【发布时间】:2011-07-14 14:21:27
【问题描述】:

如何在使用单击一次更新后重新启动 WPF 应用程序,我需要启动新版本!

【问题讨论】:

  • 更多上下文?你的意思是自动的?远程? …
  • 对于这种情况,请将 Check-for-Update 配置为在应用启动之前发生。这是发布下的一个选项。
  • @madd0:来自代码,使用 .Net 部署 API 安装单击一次更新后(来自 Application.Deployment)。
  • @Henk Holterman:但我已经在它自己的应用程序中开发了一个自定义部署,所以我不能依赖应用程序启动之前的自动更新。
  • 您是否尝试过在退出正在运行的版本之前处理.启动新版本?

标签: c# wpf deployment clickonce


【解决方案1】:

有几种方法,但大多数都不能正常工作,他们最终会重新打开旧版本。

WPF 没有适当的方法来处理它(#fixwpf)听起来很疯狂,但您需要引用System.Windows.Forms.dll 并调用System.Windows.Forms.Application.Restart();

快速搜索发现 Rob Relyea 关于同一件事的帖子(XAML、WPF Microsoft Guy) http://robrelyea.wordpress.com/2007/07/24/application-restart-for-wpf/

【讨论】:

    【解决方案2】:

    没有必要仅仅为此包含 winforms 程序集,这似乎有点矫枉过正。

    您可以在其重新启动方法中执行与 winforms 在幕后所做的相同的操作。应用更新后:

    String ApplicationEntryPoint = ApplicationDeployment.CurrentDeployment.UpdatedApplicationFullName;
    
    Process.Start(ApplicationEntryPoint);
    
    //shutdown current instance here
    

    这将通过正确的 ClickOnce 初始化启动新版本的应用程序。

    【讨论】:

    • 出于某种原因,我不得不使用String ApplicationEntryPoint = ApplicationDeployment.CurrentDeployment.UpdateLocation.AbsoluteUri;
    • 只要您的默认浏览器处理 clickonce 部署就可以工作。 Chrome 在我的情况下似乎不起作用,但仍然是不错的选择。
    • Chrome 似乎无法处理 clickonce 部署,它会显示一个 Keep/Discard 窗口。
    【解决方案3】:
            private static void RestartClickOnceApplication()
            {
                try
                {
                    XDocument xDocument;
                    using (MemoryStream memoryStream = new MemoryStream(AppDomain.CurrentDomain.ActivationContext.DeploymentManifestBytes))
                    using (XmlTextReader xmlTextReader = new XmlTextReader(memoryStream))
                    {
                        xDocument = XDocument.Load(xmlTextReader);
                    }
                    var description = xDocument.Root.Elements().Where(p => p.Name.LocalName == "description").First();
                    var publisher = description.Attributes().Where(a => a.Name.LocalName == "publisher").First();
                    var product = description.Attributes().Where(a => a.Name.LocalName == "product").First();
    
                    var path = System.Environment.GetFolderPath(System.Environment.SpecialFolder.StartMenu) + @"\Programs\";
                    path += publisher.Value + @"\" + product.Value + ".appref-ms";
    
                    if (File.Exists(path))
                    {
                        Process.Start(path);
                        Application.Current.Shutdown();
                    }
                    else
                    {
                        Application.Current.Shutdown();
                    }
                }
                catch
                {
                    Application.Current.Shutdown();
                }
            }
    

    【讨论】:

    • 谢谢!我稍微更改了此解决方案以使其对我正常工作。 var path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.StartMenu), "Programs", publisher.Value, product.Value, product.Value + ".appref-ms");
    【解决方案4】:

    一旦您启动了应用程序(即双击 .application 文件),您不会自动注意到,因为框架在启动时只为您做的一件事是检查您的本地版本是否早于应用程序下载站点中的那个。

    但是您可以使用 ApplicationDeployment-Class 来检查更新,它具有所有必要的 IIRC。

    【讨论】:

      【解决方案5】:

      使用迈克尔提供的内容:

      String ApplicationEntryPoint = ApplicationDeployment.CurrentDeployment.UpdatedApplicationFullName;
      
      Process.Start(ApplicationEntryPoint);
      

      确实存在浏览器处理不正确的问题。例如,Edge 在打开您的应用程序后会留下空白的浏览器页面。因为ApplicationDeployment.CurrentDeployment.UpdatedApplicationFullName 指的是一个长的http url 地址,所以理论上你的互联网也有可能在下载完成后瞬间掉线,因此你的应用程序不会重新启动(无法访问该url)。

      我选择了这个:

      ... Update()
      
      if (System.IO.File.Exists(Environment.GetFolderPath(Environment.SpecialFolder.StartMenu) + "\\Programs\\MyCompany\\MyApp.appref-ms"))
      {
         System.Diagnostics.Process.Start(Environment.GetFolderPath(Environment.SpecialFolder.StartMenu) + "\\Programs\\MyCompany\\MyApp.appref-ms");
      }
      else if (System.IO.File.Exists(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\MyApp.appref-ms"))
      {
         System.Diagnostics.Process.Start(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\MyApp.appref-ms");
      }
      else throw new InvalidOperationException("Cannot restart the application, because StartMenu and Desktop shortcuts are missing!");
      
      ... shut down application (this.Close() etc.)
      

      这当然假设您指定 ClickOnce 部署来创建快捷方式,并且没有人删除它们。但这样的机会非常低。 (如果没有这些快捷方式,用户可能无法执行您的应用,因为 ClickOnce 会将 .exe 部署到非常隐蔽的位置)

      如果你真的想要,你可以在最后的 else 语句中,而不是抛出异常,在 temp 目录中创建一个 appref-ms 文件(谷歌会帮助)并执行它.

      【讨论】:

      • 谢谢!你拯救了我的一天。
      【解决方案6】:

      在解决方案资源管理器中右键单击引用 > 单击添加引用 > 单击程序集 > 搜索并添加 System.Windows.Forms > 在 MainWindow 中添加“System.Windows.Forms.Application.Restart();”。

      完成!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-09-14
        • 2012-05-30
        • 2022-01-22
        • 2011-05-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多