如何使用“单击一次”构建单个实例应用程序? [英] How can I build a single instance application using Click Once?

查看:71
本文介绍了如何使用“单击一次”构建单个实例应用程序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要有一个单实例应用程序(按照 answer ),但需要通过单击一次进行部署。

I need to have a single instance application (as per this answer), but it needs to be deployed via click once.

问题是我要求单击一次不会t在应用程序运行时自动检测到更新,以尝试加载较新的版本。如果它正在运行,那么我需要使另一个实例处于活动状态。通常,在选择单击一次链接时,它要做的第一件事就是尝试查找更新。我想拦截它,并检查一个已经运行的实例之前,以启动正常的更新过程。

The problem is that I require that click once doesn't automatically detect an update an attempt to load a newer version while the application is running. If it is running, then I need the other instance to be made active. Usually, when selecting a Click Once link, the very first thing it does is attempt to find an update. I want to intercept this and check for an already running instance prior to launching the normal update process.

有人知道在内部如何做到这一点吗?单击一次部署方案?

Does anyone know how this is possible within a Click Once deployment scenario?

推荐答案

为解决该问题,我们构建了一个具有以下两个功能的原型应用程序。

To tackle the problem, we built a prototype application which has the following two functionalities.


  1. 禁用一台计算机上的多个实例。通过clickonce部署单个实例应用程序。当用户尝试启动该应用程序的第二个实例时,将弹出一条消息,指示另一个实例已在运行。

  1. Multiple instances on one pc are disabled. A single instance application is deployed via clickonce. When a user tries to start a second instance of the app, a message will pop up indicating that "Another instance is already running".

检查更新异步安装并安装更新(如果存在)。如果用户运行新实例时有可用更新,则会弹出一条消息:有可用更新。

Checks for an update asynchronously, and installs the update if one exists. A message: "An update is available" will pop up if there is an update available when a user runs a new instance.

构建演示应用程序的过程如下:

The process to build the demo application is as follows:

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更新检查(在发布-更新...对话框中)。

Step 2: Handle update programmatically

Before we do that, we should disable the automatic ClickOnce update checking (in the Publish -- Updates... dialog).

然后,我们创建两种形式:UpdateProgress和mainForm,其中UpdateProgress指示下载进度,而mainForm代表主应用程序。

Then we create two forms: UpdateProgress and mainForm, where UpdateProgress indicates download progress and mainForm represents the main application.

当用户运行应用程序时,将首先启动updateProgress来检查更新。更新完成后,mainForm将启动,并且updateProgress将被隐藏。

When a user runs the application, updateProgress will be launched firstly to check for updates. When updating completes, mainForm will start and updateProgress will be hidden.

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

应用程序运行良好,我们希望它是解决该问题的好方法。

特别感谢 Timothy Walters 用于提供源代码

The application works well and we hope it is a good solution for the problem.
Special thanks to Timothy Walters for providing the source code

这篇关于如何使用“单击一次”构建单个实例应用程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆