Frage

Ich brauche eine einzelne Instanz Anwendung haben (wie pro diese Antwort ), aber es muss einmal per Klick bereitgestellt werden.

Das Problem ist, dass ich verlangen, dass einmal klicken Update einen Versuch nicht automatisch erfassen, um eine neuere Version zu laden, während die Anwendung ausgeführt wird. Wenn es läuft, dann muss ich die andere Instanz aktiv gemacht werden. Normalerweise, wenn ein Click Once Link Auswahl, das erste, was sie tut, ist versucht, ein Update zu finden. Ich mag diese abfangen und prüfen, ob eine bereits laufende Instanz vor , um den normalen Update-Prozess zu starten.

Wer weiß, wie dies in einem Klick möglich ist Sobald Einsatzszenario?

War es hilfreich?

Lösung

Um das Problem zu bewältigen, wir bauten eine Prototyp-Anwendung, die die folgenden zwei Funktionen hat.

  1. Mehrere Instanzen auf einem PC sind deaktiviert. Eine einzelne Instanz Anwendung über Clickonce bereitgestellt. Wenn ein Benutzer eine zweite Instanz der Anwendung zu starten versucht, wird eine Meldung Pop-up darauf hinweist, dass „eine andere Instanz bereits ausgeführt wird.“

  2. Prüft, ob ein Update asynchron und installiert das Update, falls vorhanden. Eine Meldung: „Ein Update ist verfügbar“ wird angezeigt, wenn ein Update verfügbar ist, wenn ein Benutzer eine neue Instanz läuft.

Der Prozess der Demo-Anwendung zu erstellen, ist wie folgt:

Schritt 1:. Detect eine aktive Instanz Anwendung Mutex-Klasse mit

namespace ClickOnceDemo
{
    static class Program
    {
        /// summary>
        /// The main entry point for the application.
        /// /summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault( false );
            bool ok;
            var m = new System.Threading.Mutex( true, "Application", out ok );
            if ( !ok )
            {
                MessageBox.Show( "Another instance is already running.", ApplicationDeployment.CurrentDeployment.CurrentVersion.ToString() );
                return;
            }
           Application.Run( new UpdateProgress() );
        }
    }
}

Schritt 2: Griff aktualisiert programmatisch

Bevor wir das tun, sollten wir die automatische Update-Clickonce Überprüfung (im Veröffentlichen - Updates ... Dialog) deaktivieren.

Dann erstellen wir zwei Formen: Update und Mainform, wo Update Download zeigt den Fortschritt und Mainform stellt die Hauptanwendung.

Wenn ein Benutzer die Anwendung ausgeführt wird, wird Update zunächst nach Updates suchen gestartet werden. Wenn abgeschlossen ist aktualisieren, wird Mainform beginnen und Update versteckt sein.

namespace ClickOnceDemo
{
public partial class UpdateProgress : Form
 {
  public UpdateProgress()
        {
            InitializeComponent();
            Text = "Checking for updates...";

            ApplicationDeployment ad = ApplicationDeployment.CurrentDeployment;
            ad.CheckForUpdateCompleted += OnCheckForUpdateCompleted;
            ad.CheckForUpdateProgressChanged += OnCheckForUpdateProgressChanged;

            ad.CheckForUpdateAsync();
       }

        private void OnCheckForUpdateProgressChanged(object sender, DeploymentProgressChangedEventArgs e)
        {
            lblStatus.Text = String.Format( "Downloading: {0}. {1:D}K of {2:D}K downloaded.", GetProgressString( e.State ), e.BytesCompleted / 1024, e.BytesTotal / 1024 );
            progressBar1.Value = e.ProgressPercentage;
        }

        string GetProgressString( DeploymentProgressState state )
        {
            if ( state == DeploymentProgressState.DownloadingApplicationFiles )
            {
                return "application files";
            }
            if ( state == DeploymentProgressState.DownloadingApplicationInformation )
            {
                return "application manifest";
            }
            return "deployment manifest";
        }

        private void OnCheckForUpdateCompleted(object sender, CheckForUpdateCompletedEventArgs e)
        {
            if ( e.Error != null )
            {
                MessageBox.Show( "ERROR: Could not retrieve new version of the application. Reason: \n" + e.Error.Message + "\nPlease report this error to the system administrator." );
                return;
            }
            if ( e.Cancelled )
            {
                MessageBox.Show( "The update was cancelled." );
            }

            // Ask the user if they would like to update the application now.
            if ( e.UpdateAvailable )
            {
                if ( !e.IsUpdateRequired )
                {
                    long updateSize = e.UpdateSizeBytes;
                    DialogResult dr = MessageBox.Show( string.Format("An update ({0}K) is available. Would you like to update the application now?", updateSize/1024), "Update Available", MessageBoxButtons.OKCancel );
                    if ( DialogResult.OK == dr )
                    {
                        BeginUpdate();
                    }
                }
                else
                {
                    MessageBox.Show( "A mandatory update is available for your application. We will install the update now, after which we will save all of your in-progress data and restart your application." );
                    BeginUpdate();
                }
            }
            else
            {
                ShowMainForm();
            }
        }

        // Show the main application form
        private void ShowMainForm()
        {
            MainForm mainForm = new MainForm ();
            mainForm.Show();
            Hide();
        }

        private void BeginUpdate()
        {
            Text = "Downloading update...";
            ApplicationDeployment ad = ApplicationDeployment.CurrentDeployment;
            ad.UpdateCompleted += ad_UpdateCompleted;
            ad.UpdateProgressChanged += ad_UpdateProgressChanged;

            ad.UpdateAsync();
        }

        void ad_UpdateProgressChanged( object sender, DeploymentProgressChangedEventArgs e )
        {
            String progressText = String.Format( "{0:D}K out of {1:D}K downloaded - {2:D}% complete", e.BytesCompleted / 1024, e.BytesTotal / 1024, e.ProgressPercentage );
            progressBar1.Value = e.ProgressPercentage;
            lblStatus.Text = progressText;
        }

        void ad_UpdateCompleted( object sender, AsyncCompletedEventArgs e )
        {
            if ( e.Cancelled )
            {
                MessageBox.Show( "The update of the application's latest version was cancelled." );
                return;
            }
            if ( e.Error != null )
            {
                MessageBox.Show( "ERROR: Could not install the latest version of the application. Reason: \n" + e.Error.Message + "\nPlease report this error to the system administrator." );
                return;
            }

            DialogResult dr = MessageBox.Show( "The application has been updated. Restart? (If you do not restart now, the new version will not take effect until after you quit and launch the application again.)", "Restart Application", MessageBoxButtons.OKCancel );
            if ( DialogResult.OK == dr )
            {
                Application.Restart();
            }
            else
            {
                ShowMainForm();
            }
        }
    }
}

Die Anwendung funktioniert gut und wir hoffen, dass es eine gute Lösung für das Problem ist.
Besonderer Dank geht an Timothy Walters für den Quellcode bietet

Andere Tipps

Sicher - Sie die automatische Aktualisierung der Clickonce deaktivieren können Überprüfung (im Veröffentlichen -> Updates .. Dialog), dann verwenden Sie die Objekte und Befehle in dem System.Deployment.Application Namespace pragmatisch nach Updates zu suchen.

Check out:

Wenn es ein Update, können Sie einzelne Instanz Anwendung überprüft, bevor tatsächlich aktualisiert wird, durch den Aufruf:

Ich glaube nicht, Sie in der Lage sein werden es so wie die Prüfung ganz zu tun, bevor Lauf außerhalb des Codes ist.

Sie können jedoch die Clickonce-Bereitstellungsoptionen ändern für Aktualisierungen während der Ausführung von Code zu überprüfen.

Wenn Sie mehr Kontrolle benötigen, dann können Sie die ApplicationDeployment aktualisieren oder checkForUpdate Methoden zu haben absolute über den Update-Prozess.

Ich benutzen http://wpfsingleinstance.codeplex.com/ in meiner WPF Clickonce-Anwendung mit großem Erfolg. Ich habe nichts zu ändern.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top