Подтвердить что ты не робот

Как я могу откатить приложение ClickOnce?

Есть ли способ (hacky will do), позволяющий пользователю вернуться к предыдущей версии ClickOnce развернутого приложения

Я просмотрел документы и API, и, похоже, это не так. Вы можете выборочно выбирать, хотите ли вы обновить, но после обновления, похоже, нет пути назад.

4b9b3361

Ответ 1

ClickOnce будет использовать любую версию, которую вы им отправляете. Если вы отправите им старую версию, они откатынутся к этой старой версии.

Еще в мае мой приятель Дэвид написал статью о том, как это сделать для каждого пользователя. Мы можем буквально иметь каждого пользователя в другой версии. Приложение даже сообщает базе данных, какую версию хочет пользователь, поэтому они могли бы теоретически изменить свою версию, а затем просто перезапустить приложение.

Fine Grained Versioning с ClickOnce

Ответ 2

Вы можете вернуться к старой версии на стороне сервера, изменив файл манифеста сервера. Когда клиент перезапустит приложение, он увидит, что у него другая версия, чем то, что говорит сервер, это "текущая" версия, и она будет загружать новую. Этот файл манифеста сервера обычно всегда указывает на самую последнюю версию, но это необязательно.

Здесь, как изменить его (я опубликовал с помощью Visual Studio 2008. Другие версии могут иметь другую структуру папок публикации).

В той же папке, что и publish.htm, является XML документ под названием [appName].application. Это файл манифеста на стороне сервера, который клиент использует для сравнения текущей версии. В этом документе содержится текущая версия, в которой клиент должен работать, а также местоположение на сервере, которое можно найти в файлах развертывания.

В том же месте, что и publish.htm, также находится папка "Файлы приложений". Эта папка содержит вложенные папки для каждой из предыдущих изданий. Внутри каждой из этих подпапок находится другой документ XML с тем же именем, о котором я упоминал выше, под названием [appName].application. Скопируйте этот файл (из любой папки, содержащей версию, на которую вы хотите вернуться) и вставьте ее в ту же папку, что и publish.htm (на несколько уровней вверх). Когда клиентское приложение перезагрузится, оно появится точно так же, как новая версия доступна, загрузите ее и запустите. Теперь клиент будет работать с предыдущей версией.

Ответ 3

Вы можете войти в приложение "Добавить/удалить приложение" и выбрать свое приложение и выбрать, чтобы установить последнюю установку.

Ответ 4

Вы можете использовать MAGEUI для отката к предыдущей версии манифеста на сервере. Проверьте это.

Ответ 5

Если вы посмотрите на свое местоположение развертывания, вы увидите каждую предыдущую версию в отдельной папке с добавленным номером версии, а также манифест развертывания, а также с добавленным номером версии.

Вы можете переименовать любой из них в качестве текущего развертывания, а при следующем обновлении этого приложения он потянет версию, на которую вы вернулись.

Ответ 6

Я понимаю, что алгоритм проверки версий ClickOnce выглядит следующим образом:

  • Если версия, установленная на клиенте = версия, развернутая на сервере, ничего не делает
  • Если версия клиента < версия сервера - обновление
  • Если версия клиентa > версия сервера:
    • Если minimumVersion указано на клиенте >= серверная версия - покажите ошибку, поскольку у нас есть
    • Если минимальное значение, указанное на клиенте < версия сервера - понижение рейтинга
    • Если MinimumVersion не указано на клиенте - понижение рейтинга

Ответ 7

Мне просто нужно было сделать один из них на моем живом сервере, и было приятно иметь все эти заметки. Мое решение было немного другим, и я хотел добавить это как исправление. Прежде чем я начну развертывание, я всегда делаю резервную копию всей содержащей папки. Я смог скопировать всю структуру папок обратно в исходное состояние, и все сработало нормально.

Заметки об этом с осторожностью:

  • Ваша резервная копия будет большой, если приложение довольно велико или существует много версий, уже опубликованных в папке файлов приложений. Убедитесь, что у вас достаточно места (для меня нет объектов).
  • У разрешений есть неприятная тенденция кусать вас таким образом. Убедитесь, что ваше местоположение развертывания размещено для внешнего доступа, и вы проверяете все разрешения до и после восстановления.
  • Мне было полезно переработать мой пул приложений в IIS.

Ответ 8

Это можно сделать с помощью рефлексии, если вы знаете издателя 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 assemblyIdentity name*/"coolapp.app",
                /*The application assemblyIdentity version*/"10.8.62.17109",
                /*The application assemblyIdentity language*/"neutral",
                /*The application assemblyIdentity public Key Token*/"0000000000000000",
                /*The application assemblyIdentity processor architecture*/"msil",
                /*The deployment dependentAssembly name*/"coolapp.exe",
                /*The deployment dependentAssembly version*/"10.8.62.17109",
                /*The deployment dependentAssembly language*/"neutral",
                /*The deployment dependentAssembly public Key Token*/"0000000000000000",
                /*The deployment dependentAssembly processor architecture*/"msil",
                /*The deployment 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 });
            }
        }
    }
}