كيف يمكنني إنشاء تطبيق مثيل واحد باستخدام النقر مرة واحدة؟

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

  •  05-07-2019
  •  | 
  •  

سؤال

أحتاج إلى الحصول على تطبيق مثيل واحد (وفقًا لهذا إجابة)، ولكن يجب نشره عبر النقر مرة واحدة.

تكمن المشكلة في أنني أطلب النقر مرة واحدة ولا يكتشف التحديث تلقائيًا محاولة تحميل إصدار أحدث أثناء تشغيل التطبيق.إذا كان قيد التشغيل، فأنا بحاجة إلى تنشيط المثيل الآخر.عادة، عند تحديد رابط انقر مرة واحدة، فإن أول شيء يفعله هو محاولة العثور على تحديث.أريد اعتراض هذا والتحقق من وجود مثيل قيد التشغيل بالفعل قبل لبدء عملية التحديث العادية.

هل يعرف أحد كيف يكون ذلك ممكنًا ضمن سيناريو النشر "النقر مرة واحدة"؟

هل كانت مفيدة؟

المحلول

لمعالجة هذه المشكلة، قمنا ببناء تطبيق نموذجي يحتوي على الوظيفتين التاليتين.

  1. تم تعطيل مثيلات متعددة على جهاز كمبيوتر واحد.يتم نشر تطبيق مثيل واحد عبر Clickonce.عندما يحاول مستخدم بدء تشغيل مثيل ثانٍ للتطبيق، ستظهر رسالة منبثقة تشير إلى أن "مثيلًا آخر قيد التشغيل بالفعل".

  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 (في النشر -- التحديثات...الحوار).

ثم نقوم بإنشاء نموذجين: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