Comment mettre à jour votre EXE à partir de l'hôte distant - C # 4.0 - Application WPF

StackOverflow https://stackoverflow.com/questions/8409236

  •  29-10-2019
  •  | 
  •  

Question

Je souhaite mettre à jour mon EXE depuis le serveur distant. Ainsi, lorsque le bouton a cliqué sur mon application WPF, il téléchargera la télécommande et également un fichier TXT distant et remplacera les actuels dans le même dossier qui exe l'exécution. Il écrasera donc le fichier TXT et EXE actuel pendant que mon EXE s'exécute. Comment puis-je réaliser cela?

L'hôte distant est une URL comme www.mydomain.com/MyAPP.exe

Application WPF, C # 4.0

Était-ce utile?

La solution

La façon dont nous avons résolu ce problème était de créer un exe de shell en tant que celui qui a été installé et déployé initialement sur les machines clients.

Le programme exécutable "réel" est stocké dans un sous-répertoire de cette application initiale. Lorsque l'application Shell est lancée, après avoir téléchargé et installé toutes les mises à jour pour la vraie application, il lance l'exécutable de l'application réelle dans un appdomain séparé.

Voici le cœur de la "vraie" application lancement à partir de l'application Shell:

        System.AppDomainSetup oSetup = new System.AppDomainSetup();
        string sApplicationFile = null;

        // Use this to ensure that if the application is running when the user performs the update, that we don't run into file locking issues.
        oSetup.ShadowCopyFiles = "true";
        oSetup.ApplicationName = sAppName;

        // Generate the name of the DLL we are going to launch
        sApplicationFile = System.IO.Path.Combine(sApplicationDirectory, sAppName + ".exe");

        oSetup.ApplicationBase = sApplicationDirectory;
        oSetup.ConfigurationFile = sApplicationFile + ".config";
        oSetup.LoaderOptimization = LoaderOptimization.MultiDomain;

        // Launch the application
        System.AppDomain oAppDomain = AppDomain.CreateDomain(sAppName, AppDomain.CurrentDomain.Evidence, oSetup);
        oAppDomain.SetData("App", sAppName);
        oAppDomain.SetData("User", sUserName);
        oAppDomain.SetData("Pwd", sUserPassword);

        oAppDomain.ExecuteAssembly(sApplicationFile);

        // When the launched application closes, close this application as well
        Application.Exit();

Notez que dans notre version, l'application Shell collecte le nom d'utilisateur et le mot de passe de l'utilisateur afin d'accéder correctement au site Web de mise à jour. Ces données sont ensuite transmises à l'application "réelle" via le SetData Méthode sur AppDomain.

Autres conseils

La solution dépend de votre cas particulier. Mais il n'y a pas de solution droite, car vous ne pouvez pas mettre à jour des assemblages pendant qu'ils sont chargés dans la mémoire et utilisés. Je peux proposer 2 solutions: en utilisant Copie d'ombre et en utilisant une sorte d'exécutable d'assistance. Je les ai utilisés tous les deux.

Copie d'ombre.

La façon évidente est de faire en sorte que votre exécutable principal soit copié, de le remplacer pendant l'exécution de votre application, puis de redémarrer l'application. Mais toi Impossible de faire votre domaine d'application par défaut Pour être copié de l'ombre, seuls les domaines d'application secondaires peuvent l'être. Mais vous pouvez toujours déplacer tout votre code dans un autre assembly (disons, mainapplib.dll) et réécrire votre application principale exécutable (mainapp.exe) afin qu'il ne contient que du "code de chargeur". Ce code de chargeur doit créer un autre domaine d'application, le définir pour être copié de l'ombre, puis exécuter votre logique de programme dans le domaine d'application secondaire. Méfiez-vous de ne pas avoir de références directes de votre domaine d'application principal dans mainapplib.dll, car alors cet assemblage sera chargé dans votre domaine d'application principal qui n'est pas copié par l'ombre et le fichier d'assemblage sera verrouillé. Dans la plupart des cas, vous pouvez aller avec Appdomain.execuseSembly () Méthodes.

Helper Exécutable

L'idée est d'utiliser une sorte de mettre à jour le finisseur. Votre application principale reste inchangée, vous n'y ajoutez qu'une petite quantité de code, afin que votre application télécharge la mise à jour, la mettez dans un dossier temporaire, puis votre application principale commence à mettre à jour le finisseur (dans un processus distinct) et sort. La mise à jour du finisseur attend que votre application se ferme, puis copie de nouveaux fichiers à partir du dossier temporaire dans le dossier de votre application en remplacement de tous les fichiers. La mise à jour du finisseur ne peut pas remplacer son propre exécutable, mais il peut être fait par application principale avant de commencer le finisseur de mise à jour. Après la copie des fichiers, le finisseur de mise à jour exécute votre application.

ps Personnellement, je préfère l'ancienne solution car elle implique une sorte de magie vaudou à l'aide de domaines d'applic Framework MEF). Mais ce dernier est plus facile à comprendre, surtout si vous n'avez jamais travaillé avec les domaines d'applications et le chargement des assemblages manuels, c'est assez simple.

Vous pourriez probablement utiliser Cliquez (En fonction de votre commentaire ci-dessus que vous seriez prêt à avoir un autre assemblage, obtenez l'EXE .... Comme l'autre affiche l'a mentionné, vous ne pouvez pas remplacer un assemblage en cours d'exécution). Vous pouvez le configurer pour vérifier à différents moments (par exemple au démarrage) pour les nouvelles versions et les télécharger automatiquement. C'est une solution très robuste et vous pouvez faire beaucoup avec les assemblages de déploiement.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top