diff --git a/AutoUpdater.NET/AutoUpdater.cs b/AutoUpdater.NET/AutoUpdater.cs index 8db20677..f8f15ec7 100644 --- a/AutoUpdater.NET/AutoUpdater.cs +++ b/AutoUpdater.NET/AutoUpdater.cs @@ -6,6 +6,7 @@ using System.Net; using System.Net.Cache; using System.Reflection; +using System.Threading; using System.Windows.Forms; using System.Xml; using AutoUpdaterDotNET.Properties; @@ -39,6 +40,8 @@ public enum RemindLaterFormat /// public static class AutoUpdater { + private static System.Timers.Timer _remindLaterTimer; + internal static String ChangeLogURL; internal static String DownloadURL; @@ -53,6 +56,8 @@ public static class AutoUpdater internal static bool IsWinFormsApplication; + internal static bool Running; + /// /// Set the Application Title shown in Update dialog. Although AutoUpdater.NET will get it automatically, you can set this property if you like to give custom Title. /// @@ -67,6 +72,13 @@ public static class AutoUpdater /// Opens the download url in default browser if true. Very usefull if you have portable application. /// public static bool OpenDownloadPage; + + /// + /// Sets the current culture of the auto update notification window. Set this value if your application supports + /// functionalty to change the languge of the application. + /// + public static CultureInfo CurrentCulture; + /// /// If this is true users can see the skip button. @@ -113,21 +125,12 @@ public static class AutoUpdater /// /// Start checking for new version of application and display dialog to the user if update is available. /// - public static void Start() + /// Assembly to use for version checking. + public static void Start(Assembly myAssembly = null) { - Start(AppCastURL); + Start(AppCastURL, myAssembly); } - /// - /// A delegate type to handle how to exit the application after update is downloaded. - /// - public delegate void ApplicationExitEventHandler(); - - /// - /// An event that developers can use to exit the application gracefully. - /// - public static event ApplicationExitEventHandler ApplicationExitEvent; - /// /// Start checking for new version of application and display dialog to the user if update is available. /// @@ -135,17 +138,27 @@ public static void Start() /// Assembly to use for version checking. public static void Start(String appCast, Assembly myAssembly = null) { - AppCastURL = appCast; + if (!Running && _remindLaterTimer == null) + { + Running = true; + + if (CurrentCulture == null) + { + CurrentCulture = CultureInfo.CurrentCulture; + } - IsWinFormsApplication = Application.MessageLoop; + AppCastURL = appCast; - var backgroundWorker = new BackgroundWorker(); + IsWinFormsApplication = Application.MessageLoop; - backgroundWorker.DoWork += BackgroundWorkerDoWork; + var backgroundWorker = new BackgroundWorker(); - backgroundWorker.RunWorkerCompleted += BackgroundWorkerOnRunWorkerCompleted; + backgroundWorker.DoWork += BackgroundWorkerDoWork; - backgroundWorker.RunWorkerAsync(myAssembly ?? Assembly.GetEntryAssembly()); + backgroundWorker.RunWorkerCompleted += BackgroundWorkerOnRunWorkerCompleted; + + backgroundWorker.RunWorkerAsync(myAssembly ?? Assembly.GetEntryAssembly()); + } } private static void BackgroundWorkerOnRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs runWorkerCompletedEventArgs) @@ -174,8 +187,33 @@ private static void BackgroundWorkerOnRunWorkerCompleted(object sender, RunWorke { Application.EnableVisualStyles(); } - var updateForm = new UpdateForm(); - updateForm.Show(); + var backgroundworker = new BackgroundWorker(); + backgroundworker.DoWork += delegate (object o, DoWorkEventArgs eventArgs) + { + eventArgs.Cancel = true; + Thread thread = new Thread(new ThreadStart(delegate + { + var updateForm = new UpdateForm(); + if (updateForm.ShowDialog().Equals(DialogResult.OK)) + { + eventArgs.Cancel = false; + } + })); + thread.CurrentCulture = thread.CurrentUICulture = CurrentCulture; + thread.SetApartmentState(ApartmentState.STA); + thread.Start(); + thread.Join(); + }; + backgroundworker.RunWorkerCompleted += + delegate (object o, RunWorkerCompletedEventArgs eventArgs) + { + if (!eventArgs.Cancelled) + { + Exit(); + } + }; + backgroundworker.RunWorkerAsync(); + return; } else { @@ -196,6 +234,7 @@ private static void BackgroundWorkerOnRunWorkerCompleted(object sender, RunWorke } } } + Running = false; } } } @@ -385,39 +424,30 @@ private static string GetURL(Uri baseUri, XmlNode xmlNode) return temp; } - internal static void Exit(Form ownerForm) + private static void Exit() { - if (ApplicationExitEvent != null) - { - ApplicationExitEvent(); - } - else + var currentProcess = Process.GetCurrentProcess(); + foreach (var process in Process.GetProcessesByName(currentProcess.ProcessName)) { - var currentProcess = Process.GetCurrentProcess(); - foreach (var process in Process.GetProcessesByName(currentProcess.ProcessName)) + if (process.Id != currentProcess.Id) { - if (process.Id != currentProcess.Id) - { - process.Kill(); - } + process.Kill(); } + } - ownerForm.Close(); - - if (IsWinFormsApplication) - { - Application.Exit(); - } - #if NETWPF - else if (System.Windows.Application.Current != null) - { - System.Windows.Application.Current.Shutdown(); - } - #endif - else - { - Environment.Exit(0); - } + if (IsWinFormsApplication) + { + Application.Exit(); + } + #if NETWPF + else if (System.Windows.Application.Current != null) + { + System.Windows.Application.Current.Shutdown(); + } + #endif + else + { + Environment.Exit(0); } } @@ -434,16 +464,17 @@ private static Attribute GetAttribute(Assembly assembly, Type attributeType) internal static void SetTimer(DateTime remindLater) { TimeSpan timeSpan = remindLater - DateTime.Now; - var timer = new System.Timers.Timer + _remindLaterTimer = new System.Timers.Timer { - Interval = (int) timeSpan.TotalMilliseconds + Interval = (int) timeSpan.TotalMilliseconds, }; - timer.Elapsed += delegate + _remindLaterTimer.Elapsed += delegate { - timer.Stop(); + _remindLaterTimer.Stop(); + _remindLaterTimer = null; Start(); }; - timer.Start(); + _remindLaterTimer.Start(); } /// diff --git a/AutoUpdater.NET/DownloadUpdateDialog.cs b/AutoUpdater.NET/DownloadUpdateDialog.cs index 5f7a968f..aaab0057 100644 --- a/AutoUpdater.NET/DownloadUpdateDialog.cs +++ b/AutoUpdater.NET/DownloadUpdateDialog.cs @@ -81,7 +81,7 @@ private void OnDownloadComplete(object sender, AsyncCompletedEventArgs e) throw; } - AutoUpdater.Exit(this); + Close(); } private static string GetFileName(string url, string httpWebRequestMethod = "HEAD") diff --git a/AutoUpdater.NET/Resources/ZipExtractor.exe b/AutoUpdater.NET/Resources/ZipExtractor.exe index 208a6f9a..cc22901c 100644 Binary files a/AutoUpdater.NET/Resources/ZipExtractor.exe and b/AutoUpdater.NET/Resources/ZipExtractor.exe differ diff --git a/AutoUpdater.NET/UpdateForm.Designer.cs b/AutoUpdater.NET/UpdateForm.Designer.cs index b8fce756..bd309b8d 100644 --- a/AutoUpdater.NET/UpdateForm.Designer.cs +++ b/AutoUpdater.NET/UpdateForm.Designer.cs @@ -64,7 +64,6 @@ private void InitializeComponent() // // buttonUpdate // - this.buttonUpdate.DialogResult = System.Windows.Forms.DialogResult.OK; this.buttonUpdate.Image = global::AutoUpdaterDotNET.Properties.Resources.download; resources.ApplyResources(this.buttonUpdate, "buttonUpdate"); this.buttonUpdate.Name = "buttonUpdate"; @@ -73,7 +72,6 @@ private void InitializeComponent() // // buttonRemindLater // - this.buttonRemindLater.DialogResult = System.Windows.Forms.DialogResult.Cancel; this.buttonRemindLater.Image = global::AutoUpdaterDotNET.Properties.Resources.clock_go; resources.ApplyResources(this.buttonRemindLater, "buttonRemindLater"); this.buttonRemindLater.Name = "buttonRemindLater"; @@ -101,7 +99,6 @@ private void InitializeComponent() this.AcceptButton = this.buttonUpdate; resources.ApplyResources(this, "$this"); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.CancelButton = this.buttonRemindLater; this.Controls.Add(this.pictureBoxIcon); this.Controls.Add(this.labelReleaseNotes); this.Controls.Add(this.labelDescription); @@ -114,6 +111,7 @@ private void InitializeComponent() this.MaximizeBox = false; this.MinimizeBox = false; this.Name = "UpdateForm"; + this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.UpdateForm_FormClosed); this.Load += new System.EventHandler(this.UpdateFormLoad); ((System.ComponentModel.ISupportInitialize)(this.pictureBoxIcon)).EndInit(); this.ResumeLayout(false); diff --git a/AutoUpdater.NET/UpdateForm.cs b/AutoUpdater.NET/UpdateForm.cs index 9a6e91d5..e9334c51 100644 --- a/AutoUpdater.NET/UpdateForm.cs +++ b/AutoUpdater.NET/UpdateForm.cs @@ -61,12 +61,14 @@ private void ButtonUpdateClick(object sender, EventArgs e) var processStartInfo = new ProcessStartInfo(AutoUpdater.DownloadURL); Process.Start(processStartInfo); + + DialogResult = DialogResult.OK; } else { if (AutoUpdater.DownloadUpdate()) { - Close(); + DialogResult = DialogResult.OK; } } } @@ -79,7 +81,6 @@ private void ButtonSkipClick(object sender, EventArgs e) { updateKey.SetValue("version", AutoUpdater.CurrentVersion.ToString()); updateKey.SetValue("skip", 1); - Close(); } } } @@ -97,14 +98,18 @@ private void ButtonRemindLaterClick(object sender, EventArgs e) AutoUpdater.RemindLaterTimeSpan = remindLaterForm.RemindLaterFormat; AutoUpdater.RemindLaterAt = remindLaterForm.RemindLaterAt; } - if (dialogResult.Equals(DialogResult.Abort)) + else if (dialogResult.Equals(DialogResult.Abort)) { if (AutoUpdater.DownloadUpdate()) { - Close(); + DialogResult = DialogResult.OK; } return; } + else + { + return; + } } using (RegistryKey updateKey = Registry.CurrentUser.CreateSubKey(AutoUpdater.RegistryLocation)) @@ -132,7 +137,12 @@ private void ButtonRemindLaterClick(object sender, EventArgs e) AutoUpdater.SetTimer(remindLaterDateTime); } } - Close(); + DialogResult = DialogResult.Cancel; + } + + private void UpdateForm_FormClosed(object sender, FormClosedEventArgs e) + { + AutoUpdater.Running = false; } } } diff --git a/AutoUpdater.NET/UpdateForm.fr.resx b/AutoUpdater.NET/UpdateForm.fr.resx index ba3cd7b7..92443cc6 100644 --- a/AutoUpdater.NET/UpdateForm.fr.resx +++ b/AutoUpdater.NET/UpdateForm.fr.resx @@ -130,7 +130,7 @@ Mettre à jour - Rappelle plus tard + Rappeler plus tard Passer cette version diff --git a/AutoUpdaterTestWPF/MainWindow.xaml.cs b/AutoUpdaterTestWPF/MainWindow.xaml.cs index 1873d701..02e658f1 100644 --- a/AutoUpdaterTestWPF/MainWindow.xaml.cs +++ b/AutoUpdaterTestWPF/MainWindow.xaml.cs @@ -1,7 +1,10 @@ -using System.Globalization; +using System; +using System.Globalization; using System.Reflection; using System.Threading; +using System.Timers; using System.Windows; +using System.Windows.Threading; using AutoUpdaterDotNET; namespace AutoUpdaterTestWPF @@ -17,7 +20,18 @@ public MainWindow() Assembly assembly = Assembly.GetEntryAssembly(); LabelVersion.Content = $"Current Version : {assembly.GetName().Version}"; Thread.CurrentThread.CurrentCulture = Thread.CurrentThread.CurrentUICulture = new CultureInfo("fr-FR"); + AutoUpdater.LetUserSelectRemindLater = true; + AutoUpdater.RemindLaterTimeSpan = RemindLaterFormat.Minutes; + AutoUpdater.RemindLaterAt = 1; AutoUpdater.ReportErrors = true; + System.Timers.Timer timer = new System.Timers.Timer {Interval = 2 * 60 * 1000}; + timer.Elapsed += delegate(object sender, ElapsedEventArgs args) + { + Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => { + AutoUpdater.Start("http://rbsoft.org/updates/AutoUpdaterTestWPF.xml"); + })); + }; + timer.Start(); } private void ButtonCheckForUpdate_Click(object sender, RoutedEventArgs e) diff --git a/README.md b/README.md index b72a3d0c..31686c60 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ AutoUpdater.NET uses XML file located on a server to get the release information 2.0.0.0 http://rbsoft.org/downloads/AutoUpdaterTest.zip https://github.com/ravibpatel/AutoUpdater.NET/releases - false + false ```` @@ -50,10 +50,10 @@ Start method of AutoUpdater class takes URL of the XML file you uploaded to serv ## Configuration Options ### Change Language -You can change of language of the update dialog by adding following line with the above code. +You can change of language of the update dialog by adding following line with the above code. If you don't do this it will use current culture of your application. ````csharp -Thread.CurrentThread.CurrentCulture = Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture("ru"); +AutoUpdater.CurrentCulture = CultureInfo.CreateSpecificCulture("ru"); ```` In above example AutoUpdater.NET will show update dialog in russian language. @@ -104,19 +104,32 @@ AutoUpdater.RemindLaterAt = 2; In above example when user press Remind Later button of update dialog, It will remind user for update after 2 days. -## Handling Application exit logic manually +## Check updates frequently -If you like to handle Application exit logic yourself then you can use ApplicationExiEvent like below. This is very useful if you like to do something before closing the application. +You can call Start method inside Timer to check for updates frequently. + +###### WinForms ````csharp -AutoUpdater.ApplicationExitEvent += AutoUpdater_ApplicationExitEvent; +System.Timers.Timer timer = new System.Timers.Timer {Interval = 2 * 60 * 1000}; +timer.Elapsed += delegate(object sender, ElapsedEventArgs args) +{ + AutoUpdater.Start("http://rbsoft.org/updates/AutoUpdaterTestWPF.xml"); +}; +timer.Start(); +```` -private void AutoUpdater_ApplicationExitEvent() +###### WPF + +````csharp +System.Timers.Timer timer = new System.Timers.Timer {Interval = 2 * 60 * 1000}; +timer.Elapsed += delegate(object sender, ElapsedEventArgs args) { - Text = @"Closing application..."; - Thread.Sleep(5000); - Application.Exit(); -} + Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => { + AutoUpdater.Start("http://rbsoft.org/updates/AutoUpdaterTestWPF.xml"); + })); +}; +timer.Start(); ```` ## Handling updates manually