Y at-il un moyen (hacky fera) d'autoriser un utilisateur à revenir à une version précédente d'une application déployée ClickOnce network?
J'ai consulté la documentation et l'API et il semble n'y avoir aucun moyen. Vous pouvez Choisissez de manière sélective si vous souhaitez mettre à jour, mais une fois mis à jour, il n'y a apparemment aucun moyen de revenir en arrière.
ClickOnce utilisera la version que vous lui enverrez. Si vous leur envoyez une ancienne version, ils reviendront à cette ancienne version.
En mai dernier, mon ami David a écrit un article sur la procédure à suivre, utilisateur par utilisateur. Nous pouvons littéralement avoir chaque utilisateur sur une version différente. L’application indique même à la base de données la version souhaitée par l’utilisateur, afin qu’ils puissent en théorie modifier leur version puis redémarrer simplement l’application.
Vous pouvez revenir à une version plus ancienne côté serveur en modifiant le fichier manifeste du serveur. Lorsque le client redémarre l'application, il verra qu'il a une version différente de celle indiquée par le serveur comme étant la version "actuelle" et téléchargera la nouvelle. Ce fichier manifeste de serveur pointe généralement toujours vers la version la plus récente, mais ce n’est pas obligatoire.
Voici comment le modifier (j'ai publié à l'aide de Visual Studio 2008. Les autres versions peuvent avoir une structure de dossier de publication différente).
Dans le même dossier que le fichier publish.htm se trouve un XML document appelé [appName].application
. Il s'agit du fichier manifeste côté serveur que le client utilise pour comparer sa version actuelle. Le contenu de ce document inclut la version "actuelle" que le client doit exécuter, ainsi que l'emplacement sur le serveur où les fichiers de déploiement peuvent être trouvés.
Au même emplacement que publish.htm
se trouve également un dossier appelé "Fichiers d'application". Ce dossier contient des sous-dossiers pour chacune des publications précédentes. Dans chacun de ces sous-dossiers se trouve un autre document XML portant le même nom que celui mentionné ci-dessus, appelé [appName].application
. Copiez ce fichier (à partir de n'importe quel dossier contenant la version vers laquelle vous souhaitez revenir) et collez-le dans le même dossier que publish.htm
(deux niveaux ou plus). Lorsque l'application cliente redémarre, elle apparaîtra exactement comme une nouvelle version disponible, téléchargez-la et exécutez-la. Le client va maintenant exécuter une version précédente.
Vous pouvez aller dans Ajouter/Supprimer une application et sélectionner votre application, puis choisir d’obtenir la dernière installation à la place.
Vous pouvez utiliser MAGEUI pour revenir à une version antérieure du manifeste sur le serveur. Regarde ça .
Si vous regardez votre emplacement de déploiement, vous verrez toutes les versions précédentes, dans un dossier séparé avec le numéro de version ajouté, ainsi que le manifeste de déploiement, ainsi que le numéro de version ajouté.
Vous pouvez renommer n'importe lequel d'entre eux en déploiement actuel. La prochaine fois que vous mettrez à jour cette application, la version que vous avez restaurée sera intégrée.
Je comprends l’algorythme de vérification de version ClickOnce comme suit:
Cela peut être fait par réflexion si vous connaissez l'éditeur URI et le nom, le jeton de clé publique de langue de version et l'architecture du processeur du déploiement et de l'application.
Le code ci-dessous va essayer de restaurer "coolapp.app" ClickOnce application. S'il ne peut pas revenir en arrière, il essaiera de le désinstaller.
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 });
}
}
}
}
Je viens de l'utiliser pour restaurer une application clickonce développée dans Visual Studio 2017. Dans mon cas, dans le dossier racine, il n'y avait que deux fichiers; l'un appelé [nomapplication] .manifest, l'autre setup.exe.
Le .manifest [nomapplication] contenait un certain nombre de références au numéro de version actuel, mais chacune était liée à une valeur publicKeyToken, de sorte que j'étais réticent à le modifier manuellement.
Ainsi, dans le dossier Application Files, sous le sous-dossier contenant la version vers laquelle je voulais revenir, j'ai trouvé un autre [nomApplication] .manifest, que j'ai copié dans le dossier racine (après avoir sauvegardé l'original).
Et c'était ça. Cela a fonctionné pour moi et était une solution très simple. Cependant, je n'utilise pas la version minimale requise, donc je ne peux pas dire si cela l'affecterait.
Je devais juste en faire une sur mon serveur de production en direct, et c'était bien d'avoir toutes ces notes. Ma solution était un peu différente et je voulais aussi ajouter ceci comme solution. Avant de déployer en production, je sauvegarde toujours au préalable l'intégralité du dossier contenant. J'ai été en mesure de copier toute la structure de dossiers dans son état d'origine et tout a bien fonctionné.
Notes de prudence avec cette méthode: