Click Once を使用してシングル インスタンス アプリケーションを構築するにはどうすればよいですか?

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

  •  05-07-2019
  •  | 
  •  

質問

単一インスタンスのアプリケーションが必要です(これに従って) 答え) ですが、クリック 1 回でデプロイする必要があります。

問題は、アプリケーションの実行中に新しいバージョンをロードしようとしても、1 回クリックしても更新を自動的に検出しないようにする必要があることです。実行中の場合は、他のインスタンスをアクティブにする必要があります。通常、[Click Once] リンクを選択すると、最初に更新の検索が試行されます。これをインターセプトして、すでに実行中のインスタンスを確認したいと考えています 通常の更新プロセスを開始します。

Click Once 展開シナリオ内でこれがどのように可能になるか知っている人はいますか?

役に立ちましたか?

解決

この問題に対処するために、次の 2 つの機能を備えたプロトタイプ アプリケーションを構築しました。

  1. 1 台の PC 上の複数のインスタンスは無効になっています。単一インスタンスのアプリケーションは、clickonce 経由でデプロイされます。ユーザーがアプリの 2 番目のインスタンスを起動しようとすると、「別のインスタンスがすでに実行されています」というメッセージがポップアップ表示されます。

  2. 更新を非同期的に確認し、更新が存在する場合はそれをインストールします。メッセージ:ユーザーが新しいインスタンスを実行するときに利用可能なアップデートがある場合は、「アップデートが利用可能です」というポップアップが表示されます。

デモ アプリケーションを構築するプロセスは次のとおりです。

ステップ1:Mutexクラスを使用してアクティブなインスタンスアプリケーションを検出します。

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() );
        }
    }
}

ステップ2:更新をプログラムで処理する

その前に、自動 ClickOnce 更新チェックを無効にする必要があります ([公開 -- 更新...] で)。ダイアログ)。

次に、2 つのフォームを作成します。UpdateProgress と mainForm。UpdateProgress はダウンロードの進行状況を示し、mainForm はメイン アプリケーションを表します。

ユーザーがアプリケーションを実行すると、最初に updateProgress が起動され、更新を確認します。更新が完了すると、mainForm が起動し、updateProgress が非表示になります。

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();
            }
        }
    }
}

アプリケーションは正常に動作しており、問題の適切な解決策となることを願っています。
特に感謝します ティモシー・ウォルターズ ソースコードを提供するため

他のヒント

確か-ClickOnce更新の自動チェックを無効にして([公開]-> [更新]ダイアログで)、 System.Deployment.Application 名前空間を使用して、更新を実際に確認します。

チェックアウト:

更新がある場合は、次の呼び出しにより、実際に更新する前にシングルインスタンスアプリケーションのチェックを行うことができます。

実行前のチェックはコードの外部にあるため、このように実行できるとは思いません。

ただし、clickonce展開オプションを変更して、コード実行中に更新を確認できます。

さらに制御が必要な場合は、 ApplicationDeployment Update または CheckForUpdate が持つメソッド更新プロセス全体にわたって。

WPF ClickOnceアプリケーションで http://wpfsingleinstance.codeplex.com/ を使用して大成功を収めました。何も変更する必要はありませんでした。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top