Как я могу создать одноэкземплярное приложение с помощью Click Once?

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

  •  05-07-2019
  •  | 
  •  

Вопрос

Мне нужно иметь одно экземплярное приложение (согласно этому отвечать), но его необходимо развернуть одним щелчком мыши.

Проблема в том, что я требую, чтобы однократный щелчок автоматически не обнаруживал обновление и не пытался загрузить более новую версию во время работы приложения.Если он запущен, мне нужно, чтобы другой экземпляр стал активным.Обычно при выборе ссылки «Нажмите один раз» первое, что она делает, — это попытка найти обновление.Я хочу перехватить это и проверить наличие уже работающего экземпляра. прежний для запуска обычного процесса обновления.

Кто-нибудь знает, как это возможно в сценарии развертывания Click Once?

Это было полезно?

Решение

Чтобы решить эту проблему, мы создали прототип приложения, которое имеет следующие две функции.

<Ол>
  • Несколько экземпляров на одном компьютере отключены. Приложение с одним экземпляром развертывается с помощью clickonce. Когда пользователь пытается запустить второй экземпляр приложения, появляется сообщение о том, что «другой экземпляр уже запущен».

  • Асинхронно проверяет наличие обновления и устанавливает его, если оно существует. Сообщение: «Доступно обновление» появится, если будет доступно обновление, когда пользователь запускает новый экземпляр.

  • Процесс создания демонстрационного приложения выглядит следующим образом:

    Шаг 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 (в диалоговом окне «Опубликовать - Обновления ...»).

    Затем мы создаем две формы: 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 или CheckForUpdate , чтобы абсолютный процесс обновления.

    Я с большим успехом использовал http://wpfsingleinstance.codeplex.com/ в своем приложении WPF ClickOnce. Мне не нужно было ничего менять.

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top