Domanda

Voglio aggiornare il mio exe dal server remoto.Quindi, quando il pulsante fa clic sulla mia applicazione wpf, scaricherà il file remoto e anche un file txt remoto e sostituirà quelli attuali nella stessa cartella in cui è in esecuzione l'exe.Quindi sovrascriverà il file txt e exe corrente mentre il mio exe è in esecuzione.Come posso ottenerlo?

L'host remoto è un URL simile a www.mydomain.com/MyAPP.exe

applicazione wpf, c # 4.0

È stato utile?

Soluzione

Il modo in cui abbiamo risolto questo problema è stato quello di creare un exe con shell che come quello che è stato installato e distribuito inizialmente alle macchine client.

Il programma eseguibile "reale" è memorizzato in una sottodirectory di questa app iniziale.Quando viene avviata l'app Shell, dopo aver scaricato e installato eventuali aggiornamenti per l'app reale, avvia l'eseguibile dell'app reale in un appdomain separato.

Ecco il nucleo dell'App "Reale" che si avvia dall'interno dell'app 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();
.

Si noti che nella nostra versione, l'app Shell raccolga il nome utente e la password dall'utente per accedere correttamente al sito Web di aggiornamento.Questi dati vengono quindi passati all'app "reale" attraverso il metodo SetData su AppDomain.

Altri suggerimenti

La soluzione dipende dal tuo caso particolare. Ma non esiste una soluzione diretta, perché non è possibile aggiornare gli assembly mentre vengono caricati in memoria e utilizzati. Posso proporre 2 soluzioni: utilizzando la copia shadow e utilizzando una sorta di helper eseguibile. Li ho usati entrambi.

Copia shadow.

Il modo più ovvio è fare in modo che il tuo eseguibile principale venga copiato shadow, sostituirlo mentre la tua app è in esecuzione e quindi riavviare l'app. Tuttavia, non puoi fare in modo che il dominio della tua app predefinita venga copiato in modo shadow, possono esserlo solo i domini delle app secondarie. Ma puoi comunque spostare tutto il codice in un altro assembly (ad esempio MainAppLib.dll) e riscrivere l'eseguibile dell'app principale (MainApp.exe) in modo che contenga solo il "codice del caricatore". Questo codice del caricatore deve creare un altro dominio dell'app, impostarlo per la copia shadow e quindi eseguire la logica del programma nel dominio dell'app secondario. Fai attenzione a non avere riferimenti diretti dal dominio dell'app principale a MainAppLib.dll perché quindi questo assembly verrà caricato nel dominio dell'app principale che non è copiato shadow e il file di assembly verrà bloccato. Nella maggior parte dei casi puoi utilizzare AppDomain.ExecuteAssembly () metodi.

Eseguibile di supporto

L'idea è di utilizzare una sorta di aggiornamento finale . La tua app principale rimane invariata, aggiungi solo una piccola quantità di codice, in modo che la tua app scarichi l'aggiornamento, la metta nella cartella temporanea e quindi la tua app principale avvii il finisher dell'aggiornamento ( in un processo separato ) ed esce. L'aggiornamento della stazione di finitura attende la chiusura dell'app, quindi copia i nuovi file dalla cartella temporanea nella cartella dell'app sostituendo tutti i file. La stazione di finitura dell'aggiornamento non può sostituire il proprio eseguibile, ma può essere eseguita dall'applicazione principale prima di avviare la stazione di finitura dell'aggiornamento. Dopo aver copiato i file, l'aggiornamento finisher esegue l'applicazione.

p.s. Personalmente preferisco la prima soluzione perché implica una sorta di magia voodoo che utilizza domini di app, riflessioni, assembly e.t.c. E può essere evoluto utilizzando plug-in se necessario (ad es. Tramite MEF framework ). Ma quest'ultimo è più facile da capire, soprattutto se non hai mai lavorato con i domini delle app e il caricamento manuale degli assembly, è abbastanza semplice.

Probabilmente potresti utilizzare ClickOnce (in base al tuo commento soprasaresti pronto a fare in modo che un altro assembly ottenga l'exe ... come diceva l'altro poster, non puoi sostituire un assembly in esecuzione).Puoi configurarlo per controllare in diversi momenti (ad esempio all'avvio) le nuove versioni e le scarica automaticamente.È una soluzione molto robusta e puoi fare molto con gli assembly di distribuzione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top