2008-10-13 88 views
42

有沒有辦法(hacky會這樣做)讓用戶回到以前版本的ClickOnce網絡部署的應用程序?如何回滾ClickOnce應用程序?

我查看了文檔和API,似乎沒有辦法。你可以有選擇地選擇,如果你想更新,但一旦更新有,似乎沒有回頭路。

回答

18

ClickOnce將使用您發送的任何版本。如果您向他們發送舊版本,他們將回滾到舊版本。

回到五月,我的好友大衛寫了一篇關於如何在每個用戶的基礎上這樣做的文章。我們可以從字面上讓每個用戶使用不同的版本。應用程序甚至會告訴數據庫用戶需要哪個版本,所以他們理論上可以改變他們的版本,然後重新啓動應用程序。

Fine Grained Versioning with ClickOnce

+0

乾杯,這看起來很不錯! – 2008-10-13 23:34:17

6

您可以進入添加/刪除應用程序並選擇您的應用程序,然後選擇最後安裝。

+0

感謝隊友, 我會嘗試了這一點,早上! – 2008-10-13 23:03:57

+0

非常簡單的方法來回滾一個版本。感謝Patrick。 – TWood 2012-11-28 21:23:49

1

如果你看看你的部署位置,你會看到每個以前的版本,在一個單獨的文件夾中追加版本號,以及部署清單,也附加了版本號。

您可以將它們中的任何一個重命名爲當前部署,並且在您下次更新該應用程序時,它將提取回滾到的版本。

+1

能完成這項工作? - 這將是非常有用的 – 2011-09-12 08:45:09

+0

我不知道這是否會奏效。部署清單具有應用程序清單的路徑,但我相信應用程序清單中也有一個版本。你也不能不更新它,而不會退出。 – 2014-10-06 05:48:36

76

通過更改服務器清單文件,您可以恢復到服務器端的舊版本。當客戶端重新啓動應用程序時,它會看到它的版本與服務器所說的'當前'版本不同,它會下載新的版本。這個服務器清單文件通常總是指向最新的版本,但並不一定。

以下是如何更改它(我使用Visual Studio 2008發佈的。其他版本可能有不同的發佈文件夾結構)。

與publish.htm位於同一文件夾中的XML文檔名爲[appName].application。這是客戶端用來比較其當前版本的服務器端清單文件。本文檔包含客戶端應運行的'當前'版本以及服務器上可以找到部署文件的位置。

在與publish.htm相同的位置也是一個名爲「應用程序文件」的文件夾。此文件夾包含以前每個發佈的子文件夾。在這些子文件夾中的每個文件夾中都有另一個與我上面提到的名稱相同的XML文檔,名稱爲[appName].application。複製此文件(從包含要恢復的版本的任何文件夾中)並將其粘貼到與publish.htm(幾個級別)相同的文件夾中。當客戶端應用程序重新啓動時,它將顯示爲可用的新版本,下載並運行它。客戶端現在將運行以前的版本。

0

我只需要在我的現場製作服務器上完成其中的一項工作,並且很高興有這些筆記。我的解決方案有點不同,我想補充一點。在我進行生產部署之前,我總是事先備份整個包含的文件夾。我能夠將我的整個文件夾結構複製回原始狀態,並且一切正常。

謹慎

注意用這種方法:如果應用程序是相當大的,還是有很多已經發表在應用程序文件夾版本的

  • 您的備份將是大的。確保你有足夠的空間(對於我來說存儲是沒有對象的)。
  • 權限有一個惡毒的傾向,咬你這種方式。確保您的部署位置是否承載了外部訪問,以便在恢復之前和之後驗證所有權限。
  • 這有助於我回收我的應用程序池IIS
0

如果您知道發佈方URI以及部署和應用程序的名稱,版本語言公鑰標記和處理器體系結構,則可以通過反射完成此操作。

以下代碼將嘗試回滾「coolapp.app」ClickOnce應用程序。如果無法回滾,則會嘗試將其卸載。

using System; 
using System.Deployment.Application; 
using System.Reflection; 

namespace ClickOnceAppRollback 
{ 
    static class Program 
    { 
     /// <summary> 
     /// The main entry point for the application. 
     /// </summary> 
     static void Main() 
     { 
      string appId = string.Format("{0}#{1}, Version={2}, Culture={3}, PublicKeyToken={4}, processorArchitecture={5}/{6}, Version={7}, Culture={8}, PublicKeyToken={9}, processorArchitecture={10}, type={11}", 
       /*The URI location of the app*/@"http://www.microsoft.com/coolapp.exe.application", 
       /*The application's assemblyIdentity name*/"coolapp.app", 
       /*The application's assemblyIdentity version*/"10.8.62.17109", 
       /*The application's assemblyIdentity language*/"neutral", 
       /*The application's assemblyIdentity public Key Token*/"0000000000000000", 
       /*The application's assemblyIdentity processor architecture*/"msil", 
       /*The deployment's dependentAssembly name*/"coolapp.exe", 
       /*The deployment's dependentAssembly version*/"10.8.62.17109", 
       /*The deployment's dependentAssembly language*/"neutral", 
       /*The deployment's dependentAssembly public Key Token*/"0000000000000000", 
       /*The deployment's dependentAssembly processor architecture*/"msil", 
       /*The deployment's dependentAssembly type*/"win32"); 

      var ctor = typeof(ApplicationDeployment).GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[] { typeof(string) }, null); 
      var appDeployment = ctor.Invoke(new object[] { appId }); 

      var subState = appDeployment.GetType().GetField("_subState", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(appDeployment); 
      var subStore = appDeployment.GetType().GetField("_subStore", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(appDeployment); 
      try 
      { 
       subStore.GetType().GetMethod("RollbackSubscription").Invoke(subStore, new object[] { subState }); 
      } 
      catch 
      { 
       subStore.GetType().GetMethod("UninstallSubscription").Invoke(subStore, new object[] { subState }); 
      } 
     } 
    } 
} 
1

我明白ClickOnce版本檢查algorythm如下:

  1. 如果在客戶端安裝的版本=版本部署到服務器 - 什麼都不做
  2. 如果客戶端版本<服務器版本 - 升級
  3. 如果客戶端版本>服務器版本:
    1. 如果在客戶端> =服務器版本上指定minimumVersion - 顯示錯誤,因爲我們有
    2. 如果客戶指定minimumVersion <服務器版本 - 降級
    3. 如果客戶未指定minimumVersion是 - 降級