Merge pull request #2086 from Vest/refactor_webclient

Use async HttpClient instead of obsolete WebClient
This commit is contained in:
Dimitrij
2021-12-16 17:31:06 +00:00
committed by GitHub
6 changed files with 164 additions and 426 deletions

View File

@@ -5,6 +5,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
## [Unreleased]
### Added
- #2086: Replace WebClient with async HttpClient for updater.
- #1850: Minify config xml
- #1770: Added missing RDP performance settings
- #1516: added API to access credential vault (Thycotic Secret Server) by specifying SSAPI:ID as username
@@ -38,7 +39,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
- #1720: Show configuration file name in title of password prompt form
- #1713: Sound redirection does not work if Clipboard redirection is set to No
- #1632: 1.77.1 breaks RDP drive and sound redirection
- #1610: Menu bar changes to english when cancelling options form
- #1610: Menu bar changes to english when canceling options form
- #1595: Unhandled exception when trying to browse through non existent multi ssh history with keyboard key strokes
- #1589: Update SQL tables instead of rewriting them
- #1465: REGRESSION: Smart Cards redirection to Remote Desktop not working

View File

@@ -2,6 +2,7 @@
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.Threading.Tasks;
using mRemoteNG.App.Info;
using mRemoteNG.App.Initialization;
using mRemoteNG.App.Update;
@@ -65,7 +66,7 @@ namespace mRemoteNG.App
Runtime.ConnectionsService.RemoteConnectionsSyncronizer.Enable();
}
public void CheckForUpdate()
public async Task CheckForUpdate()
{
if (_appUpdate == null)
{
@@ -87,32 +88,9 @@ namespace mRemoteNG.App
return;
}
_appUpdate.GetUpdateInfoCompletedEvent += GetUpdateInfoCompleted;
_appUpdate.GetUpdateInfoAsync();
}
private void GetUpdateInfoCompleted(object sender, AsyncCompletedEventArgs e)
{
if (_frmMain.InvokeRequired)
{
_frmMain.Invoke(new AsyncCompletedEventHandler(GetUpdateInfoCompleted), sender, e);
return;
}
try
{
_appUpdate.GetUpdateInfoCompletedEvent -= GetUpdateInfoCompleted;
if (e.Cancelled)
{
return;
}
if (e.Error != null)
{
throw e.Error;
}
await _appUpdate.GetUpdateInfoAsync();
if (_appUpdate.IsUpdateAvailable())
{
Windows.Show(WindowType.Update);
@@ -120,7 +98,7 @@ namespace mRemoteNG.App
}
catch (Exception ex)
{
Runtime.MessageCollector.AddExceptionMessage("GetUpdateInfoCompleted() failed.", ex);
Runtime.MessageCollector.AddExceptionMessage("CheckForUpdate() failed.", ex);
}
}
}

View File

@@ -1,12 +1,12 @@
using System;
using System.IO;
using System.Net;
using System.ComponentModel;
using System.Net.Http;
using System.Threading;
using System.Reflection;
using mRemoteNG.App.Info;
using mRemoteNG.Security.SymmetricEncryption;
using System.Security.Cryptography;
using System.Threading.Tasks;
using mRemoteNG.Properties;
#if !PORTABLE
using mRemoteNG.Tools;
@@ -21,29 +21,30 @@ namespace mRemoteNG.App.Update
{
public class AppUpdater
{
private const int _bufferLength = 8192;
private WebProxy _webProxy;
private Thread _getUpdateInfoThread;
private Thread _getChangeLogThread;
private HttpClient _httpClient;
private CancellationTokenSource _changeLogCancelToken;
private CancellationTokenSource _getUpdateInfoCancelToken;
#region Public Properties
public UpdateInfo CurrentUpdateInfo { get; private set; }
public string ChangeLog { get; private set; }
public bool IsGetUpdateInfoRunning
{
get { return _getUpdateInfoThread != null && _getUpdateInfoThread.IsAlive; }
get
{
return _getUpdateInfoCancelToken != null;
}
}
private bool IsGetChangeLogRunning
{
get { return _getChangeLogThread != null && _getChangeLogThread.IsAlive; }
}
public bool IsDownloadUpdateRunning
get
{
get { return _downloadUpdateWebClient != null; }
return _changeLogCancelToken != null;
}
}
#endregion
@@ -52,10 +53,10 @@ namespace mRemoteNG.App.Update
public AppUpdater()
{
SetProxySettings();
SetDefaultProxySettings();
}
private void SetProxySettings()
private void SetDefaultProxySettings()
{
var shouldWeUseProxy = Settings.Default.UpdateUseProxy;
var proxyAddress = Settings.Default.UpdateProxyAddress;
@@ -78,13 +79,14 @@ namespace mRemoteNG.App.Update
if (useProxy && !string.IsNullOrEmpty(address))
{
_webProxy = port != 0 ? new WebProxy(address, port) : new WebProxy(address);
_webProxy.Credentials = useAuthentication ? new NetworkCredential(username, password) : null;
}
else
{
_webProxy = null;
}
UpdateHttpClient();
}
public bool IsUpdateAvailable()
@@ -97,53 +99,23 @@ namespace mRemoteNG.App.Update
return CurrentUpdateInfo.Version > GeneralAppInfo.GetApplicationVersion();
}
public void GetUpdateInfoAsync()
public async Task DownloadUpdateAsync(IProgress<int> progress)
{
if (IsGetUpdateInfoRunning)
{
_getUpdateInfoThread.Abort();
}
_getUpdateInfoCancelToken.Cancel();
_getUpdateInfoCancelToken.Dispose();
_getUpdateInfoCancelToken = null;
_getUpdateInfoThread = new Thread(GetUpdateInfo);
_getUpdateInfoThread.SetApartmentState(ApartmentState.STA);
_getUpdateInfoThread.IsBackground = true;
_getUpdateInfoThread.Start();
}
public void GetChangeLogAsync()
{
if (CurrentUpdateInfo == null || !CurrentUpdateInfo.IsValid)
{
throw new InvalidOperationException(
"CurrentUpdateInfo is not valid. GetUpdateInfoAsync() must be called before calling GetChangeLogAsync().");
}
if (IsGetChangeLogRunning)
{
_getChangeLogThread.Abort();
}
_getChangeLogThread = new Thread(GetChangeLog);
_getChangeLogThread.SetApartmentState(ApartmentState.STA);
_getChangeLogThread.IsBackground = true;
_getChangeLogThread.Start();
}
public void DownloadUpdateAsync()
{
if (_downloadUpdateWebClient != null)
{
throw new InvalidOperationException("A previous call to DownloadUpdateAsync() is still in progress.");
}
if (CurrentUpdateInfo == null || !CurrentUpdateInfo.IsValid)
{
throw new InvalidOperationException(
"CurrentUpdateInfo is not valid. GetUpdateInfoAsync() must be called before calling DownloadUpdateAsync().");
throw new InvalidOperationException("CurrentUpdateInfo is not valid. GetUpdateInfoAsync() must be called before calling DownloadUpdateAsync().");
}
#if !PORTABLE
CurrentUpdateInfo.UpdateFilePath =
Path.Combine(Path.GetTempPath(), Path.ChangeExtension(Path.GetRandomFileName(), "msi"));
CurrentUpdateInfo.UpdateFilePath = Path.Combine(Path.GetTempPath(), Path.ChangeExtension(Path.GetRandomFileName(), "msi"));
#else
var sfd = new SaveFileDialog
{
@@ -160,135 +132,38 @@ namespace mRemoteNG.App.Update
return;
}
#endif
DownloadUpdateWebClient.DownloadFileAsync(CurrentUpdateInfo.DownloadAddress,
CurrentUpdateInfo.UpdateFilePath);
}
#endregion
#region Private Properties
private WebClient _downloadUpdateWebClient;
private WebClient DownloadUpdateWebClient
{
get
{
if (_downloadUpdateWebClient != null)
{
return _downloadUpdateWebClient;
}
_downloadUpdateWebClient = CreateWebClient();
_downloadUpdateWebClient.DownloadProgressChanged += DownloadUpdateProgressChanged;
_downloadUpdateWebClient.DownloadFileCompleted += DownloadUpdateCompleted;
return _downloadUpdateWebClient;
}
}
#endregion
#region Private Methods
private WebClient CreateWebClient()
{
var webClient = new WebClient();
webClient.Headers.Add("user-agent", GeneralAppInfo.UserAgent);
webClient.Proxy = _webProxy;
return webClient;
}
private static DownloadStringCompletedEventArgs NewDownloadStringCompletedEventArgs(string result,
Exception exception,
bool cancelled,
object userToken)
{
var type = typeof(DownloadStringCompletedEventArgs);
const BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Instance;
Type[] argumentTypes = {typeof(string), typeof(Exception), typeof(bool), typeof(object)};
var constructor = type.GetConstructor(bindingFlags, null, argumentTypes, null);
object[] arguments = {result, exception, cancelled, userToken};
if (constructor == null)
return null;
return (DownloadStringCompletedEventArgs)constructor.Invoke(arguments);
}
private DownloadStringCompletedEventArgs DownloadString(Uri address)
{
var webClient = CreateWebClient();
var result = string.Empty;
Exception exception = null;
var cancelled = false;
try
{
result = webClient.DownloadString(address);
}
catch (ThreadAbortException)
_getUpdateInfoCancelToken = new CancellationTokenSource();
using var response = await _httpClient.GetAsync(CurrentUpdateInfo.DownloadAddress, HttpCompletionOption.ResponseHeadersRead, _getUpdateInfoCancelToken.Token);
var buffer = new byte[_bufferLength];
var totalBytes = response.Content.Headers.ContentLength ?? 0;
var readBytes = 0L;
await using (var httpStream = await response.Content.ReadAsStreamAsync(_getUpdateInfoCancelToken.Token))
{
cancelled = true;
}
catch (Exception ex)
await using var fileStream = new FileStream(CurrentUpdateInfo.UpdateFilePath, FileMode.Create,
FileAccess.Write, FileShare.None, _bufferLength, true);
while (readBytes <= totalBytes || !_getUpdateInfoCancelToken.IsCancellationRequested)
{
exception = ex;
var bytesRead =
await httpStream.ReadAsync(buffer, 0, _bufferLength, _getUpdateInfoCancelToken.Token);
if (bytesRead == 0)
{
progress.Report(100);
break;
}
return NewDownloadStringCompletedEventArgs(result, exception, cancelled, null);
}
await fileStream.WriteAsync(buffer, 0, bytesRead, _getUpdateInfoCancelToken.Token);
private void GetUpdateInfo()
{
var e = DownloadString(UpdateChannelInfo.GetUpdateChannelInfo());
readBytes += bytesRead;
if (!e.Cancelled && e.Error == null)
{
try
{
CurrentUpdateInfo = UpdateInfo.FromString(e.Result);
Settings.Default.CheckForUpdatesLastCheck = DateTime.UtcNow;
if (!Settings.Default.UpdatePending)
{
Settings.Default.UpdatePending = IsUpdateAvailable();
}
}
catch (Exception ex)
{
e = NewDownloadStringCompletedEventArgs(e.Result, ex, e.Cancelled, null);
var percentComplete = (int)(readBytes * 100 / totalBytes);
progress.Report(percentComplete);
}
}
GetUpdateInfoCompletedEventEvent?.Invoke(this, e);
}
private void GetChangeLog()
{
var e = DownloadString(CurrentUpdateInfo.ChangeLogAddress);
if (!e.Cancelled && e.Error == null)
{
ChangeLog = e.Result;
}
GetChangeLogCompletedEventEvent?.Invoke(this, e);
}
private void DownloadUpdateProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
DownloadUpdateProgressChangedEventEvent?.Invoke(sender, e);
}
private void DownloadUpdateCompleted(object sender, AsyncCompletedEventArgs e)
{
var raiseEventArgs = e;
if (!e.Cancelled && e.Error == null)
{
try
{
#if !PORTABLE
var updateAuthenticode = new Authenticode(CurrentUpdateInfo.UpdateFilePath)
{
@@ -307,101 +182,85 @@ namespace mRemoteNG.App.Update
}
#endif
using (var cksum = SHA512.Create())
{
using (var stream = File.OpenRead(CurrentUpdateInfo.UpdateFilePath))
{
var hash = cksum.ComputeHash(stream);
using var checksum = SHA512.Create();
await using var stream = File.OpenRead(CurrentUpdateInfo.UpdateFilePath);
var hash = await checksum.ComputeHashAsync(stream);
var hashString = BitConverter.ToString(hash).Replace("-", "").ToUpperInvariant();
if (!hashString.Equals(CurrentUpdateInfo.Checksum))
throw new Exception("SHA512 Hashes didn't match!");
} finally{
_getUpdateInfoCancelToken?.Dispose();
_getUpdateInfoCancelToken = null;
}
}
}
catch (Exception ex)
{
raiseEventArgs = new AsyncCompletedEventArgs(ex, false, null);
}
}
if (raiseEventArgs.Cancelled || raiseEventArgs.Error != null)
{
File.Delete(CurrentUpdateInfo.UpdateFilePath);
}
DownloadUpdateCompletedEventEvent?.Invoke(this, raiseEventArgs);
_downloadUpdateWebClient.Dispose();
_downloadUpdateWebClient = null;
}
#endregion
#region Events
#region Private Methods
private AsyncCompletedEventHandler GetUpdateInfoCompletedEventEvent;
public event AsyncCompletedEventHandler GetUpdateInfoCompletedEvent
private void UpdateHttpClient()
{
add
if (_httpClient != null)
{
GetUpdateInfoCompletedEventEvent =
(AsyncCompletedEventHandler)Delegate.Combine(GetUpdateInfoCompletedEventEvent, value);
_httpClient.Dispose();
}
remove
var httpClientHandler = new HttpClientHandler();
if (_webProxy != null)
{
GetUpdateInfoCompletedEventEvent =
(AsyncCompletedEventHandler)Delegate.Remove(GetUpdateInfoCompletedEventEvent, value);
httpClientHandler.UseProxy = true;
httpClientHandler.Proxy = _webProxy;
}
_httpClient = new HttpClient(httpClientHandler);
_httpClient.DefaultRequestHeaders.UserAgent.ParseAdd(GeneralAppInfo.UserAgent);
}
public async Task GetUpdateInfoAsync()
{
if (IsGetUpdateInfoRunning)
{
_getUpdateInfoCancelToken.Cancel();
_getUpdateInfoCancelToken.Dispose();
_getUpdateInfoCancelToken = null;
}
try
{
_getUpdateInfoCancelToken = new CancellationTokenSource();
var updateInfo = await _httpClient.GetStringAsync(UpdateChannelInfo.GetUpdateChannelInfo(), _getUpdateInfoCancelToken.Token);
CurrentUpdateInfo = UpdateInfo.FromString(updateInfo);
Settings.Default.CheckForUpdatesLastCheck = DateTime.UtcNow;
if (!Settings.Default.UpdatePending)
{
Settings.Default.UpdatePending = IsUpdateAvailable();
}
}
finally
{
_getUpdateInfoCancelToken?.Dispose();
_getUpdateInfoCancelToken = null;
}
}
private AsyncCompletedEventHandler GetChangeLogCompletedEventEvent;
public event AsyncCompletedEventHandler GetChangeLogCompletedEvent
public async Task<string> GetChangeLogAsync()
{
add
if (IsGetChangeLogRunning)
{
GetChangeLogCompletedEventEvent =
(AsyncCompletedEventHandler)Delegate.Combine(GetChangeLogCompletedEventEvent, value);
}
remove
{
GetChangeLogCompletedEventEvent =
(AsyncCompletedEventHandler)Delegate.Remove(GetChangeLogCompletedEventEvent, value);
}
_changeLogCancelToken.Cancel();
_changeLogCancelToken.Dispose();
_changeLogCancelToken = null;
}
private DownloadProgressChangedEventHandler DownloadUpdateProgressChangedEventEvent;
public event DownloadProgressChangedEventHandler DownloadUpdateProgressChangedEvent
try
{
add
{
DownloadUpdateProgressChangedEventEvent =
(DownloadProgressChangedEventHandler)Delegate.Combine(DownloadUpdateProgressChangedEventEvent,
value);
_changeLogCancelToken = new CancellationTokenSource();
return await _httpClient.GetStringAsync(CurrentUpdateInfo.ChangeLogAddress, _changeLogCancelToken.Token);
}
remove
finally
{
DownloadUpdateProgressChangedEventEvent =
(DownloadProgressChangedEventHandler)Delegate.Remove(DownloadUpdateProgressChangedEventEvent,
value);
}
}
private AsyncCompletedEventHandler DownloadUpdateCompletedEventEvent;
public event AsyncCompletedEventHandler DownloadUpdateCompletedEvent
{
add
{
DownloadUpdateCompletedEventEvent =
(AsyncCompletedEventHandler)Delegate.Combine(DownloadUpdateCompletedEventEvent, value);
}
remove
{
DownloadUpdateCompletedEventEvent =
(AsyncCompletedEventHandler)Delegate.Remove(DownloadUpdateCompletedEventEvent, value);
_changeLogCancelToken?.Dispose();
_changeLogCancelToken = null;
}
}

View File

@@ -159,8 +159,6 @@ namespace mRemoteNG.UI.Forms.OptionsPages
#endregion
#region Private Methods
#region Event Handlers
private void chkCheckForUpdatesOnStartup_CheckedChanged(object sender, EventArgs e)
@@ -194,7 +192,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages
}
}
private void btnTestProxy_Click(object sender, EventArgs e)
private async void btnTestProxy_Click(object sender, EventArgs e)
{
if (_appUpdate != null)
{
@@ -210,51 +208,15 @@ namespace mRemoteNG.UI.Forms.OptionsPages
(int)numProxyPort.Value, chkUseProxyAuthentication.Checked,
txtProxyUsername.Text,
txtProxyPassword.Text);
try
{
btnTestProxy.Enabled = false;
btnTestProxy.Text = Language.OptionsProxyTesting;
_appUpdate.GetUpdateInfoCompletedEvent += GetUpdateInfoCompleted;
_appUpdate.GetUpdateInfoAsync();
}
private void chkUseProxyAuthentication_CheckedChanged(object sender, EventArgs e)
{
if (chkUseProxyForAutomaticUpdates.Checked)
{
tblProxyAuthentication.Enabled = chkUseProxyAuthentication.Checked;
}
}
#endregion
private void GetUpdateInfoCompleted(object sender, AsyncCompletedEventArgs e)
{
if (InvokeRequired)
{
AsyncCompletedEventHandler myDelegate = GetUpdateInfoCompleted;
Invoke(myDelegate, sender, e);
return;
}
try
{
_appUpdate.GetUpdateInfoCompletedEvent -= GetUpdateInfoCompleted;
await _appUpdate.GetUpdateInfoAsync();
btnTestProxy.Enabled = true;
btnTestProxy.Text = Language.TestProxy;
if (e.Cancelled)
{
return;
}
if (e.Error != null)
{
throw e.Error;
}
CTaskDialog.ShowCommandBox(this, Application.ProductName, Language.ProxyTestSucceeded, "",
Language._Ok, false);
}
@@ -266,6 +228,15 @@ namespace mRemoteNG.UI.Forms.OptionsPages
ESysIcons.Error,
0);
}
}
private void chkUseProxyAuthentication_CheckedChanged(object sender, EventArgs e)
{
if (chkUseProxyForAutomaticUpdates.Checked)
{
tblProxyAuthentication.Enabled = chkUseProxyAuthentication.Checked;
}
}
#endregion

View File

@@ -25,6 +25,7 @@ using System.Globalization;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using mRemoteNG.UI.Panels;
using WeifenLuo.WinFormsUI.Docking;
@@ -339,10 +340,10 @@ namespace mRemoteNG.UI.Forms
}
}
private void frmMain_Shown(object sender, EventArgs e)
private async void frmMain_Shown(object sender, EventArgs e)
{
PromptForUpdatesPreference();
CheckForUpdates();
await CheckForUpdates();
}
private void PromptForUpdatesPreference()
@@ -374,7 +375,7 @@ namespace mRemoteNG.UI.Forms
}
}
private void CheckForUpdates()
private async Task CheckForUpdates()
{
if (!Settings.Default.CheckForUpdatesOnStartup) return;
@@ -385,7 +386,7 @@ namespace mRemoteNG.UI.Forms
if (!IsHandleCreated)
CreateHandle(); // Make sure the handle is created so that InvokeRequired returns the correct result
Startup.Instance.CheckForUpdate();
await Startup.Instance.CheckForUpdate();
}
private void frmMain_FormClosing(object sender, FormClosingEventArgs e)

View File

@@ -1,9 +1,7 @@
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Net;
using System.Windows.Forms;
using mRemoteNG.App;
using mRemoteNG.App.Update;
@@ -11,13 +9,14 @@ using mRemoteNG.Messages;
using mRemoteNG.Themes;
using WeifenLuo.WinFormsUI.Docking;
using mRemoteNG.Resources.Language;
using System.Threading.Tasks;
namespace mRemoteNG.UI.Window
{
public partial class UpdateWindow : BaseWindow
{
private AppUpdater _appUpdate;
private bool _isUpdateDownloadHandlerDeclared;
//private bool _isUpdateDownloadHandlerDeclared;
#region Public Methods
@@ -38,12 +37,12 @@ namespace mRemoteNG.UI.Window
#region Form Stuff
private void Update_Load(object sender, EventArgs e)
private async void Update_Load(object sender, EventArgs e)
{
ApplyTheme();
ThemeManager.getInstance().ThemeChanged += ApplyTheme;
ApplyLanguage();
CheckForUpdate();
await CheckForUpdateAsync();
}
private new void ApplyTheme()
@@ -72,14 +71,14 @@ namespace mRemoteNG.UI.Window
lblLatestVersionLabel.Text = $"{Language.AvailableVersion}:";
}
private void btnCheckForUpdate_Click(object sender, EventArgs e)
private async void btnCheckForUpdate_Click(object sender, EventArgs e)
{
CheckForUpdate();
await CheckForUpdateAsync();
}
private void btnDownload_Click(object sender, EventArgs e)
private async void btnDownload_Click(object sender, EventArgs e)
{
DownloadUpdate();
await DownloadUpdateAsync();
}
private void pbUpdateImage_Click(object sender, EventArgs e)
@@ -97,7 +96,7 @@ namespace mRemoteNG.UI.Window
#region Private Methods
private void CheckForUpdate()
private async Task CheckForUpdateAsync()
{
if (_appUpdate == null)
{
@@ -119,39 +118,15 @@ namespace mRemoteNG.UI.Window
SetVisibilityOfUpdateControls(false);
_appUpdate.GetUpdateInfoCompletedEvent += GetUpdateInfoCompleted;
_appUpdate.GetUpdateInfoAsync();
}
private void GetUpdateInfoCompleted(object sender, AsyncCompletedEventArgs e)
{
if (InvokeRequired)
{
var myDelegate = new AsyncCompletedEventHandler(GetUpdateInfoCompleted);
Invoke(myDelegate, sender, e);
return;
}
try
{
_appUpdate.GetUpdateInfoCompletedEvent -= GetUpdateInfoCompleted;
await _appUpdate.GetUpdateInfoAsync();
lblInstalledVersion.Text = Application.ProductVersion;
lblInstalledVersion.Visible = true;
lblInstalledVersionLabel.Visible = true;
btnCheckForUpdate.Visible = true;
if (e.Cancelled)
{
return;
}
if (e.Error != null)
{
throw e.Error;
}
if (_appUpdate.IsUpdateAvailable())
{
lblStatus.Text = Language.UpdateAvailable;
@@ -174,8 +149,15 @@ namespace mRemoteNG.UI.Window
pbUpdateImage.Visible = true;
}
_appUpdate.GetChangeLogCompletedEvent += GetChangeLogCompleted;
_appUpdate.GetChangeLogAsync();
try
{
var changeLog = await _appUpdate.GetChangeLogAsync();
txtChangeLog.Text = changeLog.Replace("\n", Environment.NewLine);
}
catch (Exception ex)
{
Runtime.MessageCollector?.AddExceptionStackTrace(Language.UpdateGetChangeLogFailed, ex);
}
btnDownload.Focus();
}
@@ -209,33 +191,7 @@ namespace mRemoteNG.UI.Window
prgbDownload.Visible = visible;
}
private void GetChangeLogCompleted(object sender, AsyncCompletedEventArgs e)
{
if (InvokeRequired)
{
var myDelegate = new AsyncCompletedEventHandler(GetChangeLogCompleted);
Invoke(myDelegate, sender, e);
return;
}
try
{
_appUpdate.GetChangeLogCompletedEvent -= GetChangeLogCompleted;
if (e.Cancelled)
return;
if (e.Error != null)
throw e.Error;
txtChangeLog.Text = _appUpdate.ChangeLog.Replace("\n", Environment.NewLine);
}
catch (Exception ex)
{
Runtime.MessageCollector?.AddExceptionStackTrace(Language.UpdateGetChangeLogFailed, ex);
}
}
private void DownloadUpdate()
private async Task DownloadUpdateAsync()
{
try
{
@@ -243,42 +199,11 @@ namespace mRemoteNG.UI.Window
prgbDownload.Visible = true;
prgbDownload.Value = 0;
if (_isUpdateDownloadHandlerDeclared == false)
{
_appUpdate.DownloadUpdateProgressChangedEvent += DownloadUpdateProgressChanged;
_appUpdate.DownloadUpdateCompletedEvent += DownloadUpdateCompleted;
_isUpdateDownloadHandlerDeclared = true;
}
await _appUpdate.DownloadUpdateAsync(new Progress<int>(progress => prgbDownload.Value = progress));
_appUpdate.DownloadUpdateAsync();
}
catch (Exception ex)
{
Runtime.MessageCollector?.AddExceptionStackTrace(Language.UpdateDownloadFailed, ex);
}
}
#endregion
#region Events
private void DownloadUpdateProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
prgbDownload.Value = e.ProgressPercentage;
}
private void DownloadUpdateCompleted(object sender, AsyncCompletedEventArgs e)
{
try
{
btnDownload.Enabled = true;
prgbDownload.Visible = false;
if (e.Cancelled)
return;
if (e.Error != null)
throw e.Error;
if (Runtime.IsPortableEdition)
MessageBox.Show(Language.UpdatePortableDownloadComplete, Language.CheckForUpdates,
MessageBoxButtons.OK, MessageBoxIcon.Information);
@@ -297,8 +222,11 @@ namespace mRemoteNG.UI.Window
}
catch (Exception ex)
{
Runtime.MessageCollector?.AddExceptionStackTrace(Language.UpdateDownloadFailed, ex);
Runtime.MessageCollector?.AddExceptionStackTrace(Language.UpdateDownloadCompleteFailed, ex);
Runtime.MessageCollector?.AddMessage(MessageClass.ErrorMsg, ex.Message);
}
}