diff --git a/mRemoteNG/App/Startup.cs b/mRemoteNG/App/Startup.cs index cb54bc552..ee6a6816e 100644 --- a/mRemoteNG/App/Startup.cs +++ b/mRemoteNG/App/Startup.cs @@ -65,7 +65,7 @@ namespace mRemoteNG.App Runtime.ConnectionsService.RemoteConnectionsSyncronizer.Enable(); } - public void CheckForUpdate() + public async void CheckForUpdate() { if (_appUpdate == null) { @@ -87,32 +87,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 +97,7 @@ namespace mRemoteNG.App } catch (Exception ex) { - Runtime.MessageCollector.AddExceptionMessage("GetUpdateInfoCompleted() failed.", ex); + Runtime.MessageCollector.AddExceptionMessage("CheckForUpdate() failed.", ex); } } } diff --git a/mRemoteNG/App/Update/AppUpdater.cs b/mRemoteNG/App/Update/AppUpdater.cs index 5c21574c2..e7c0e4bf2 100644 --- a/mRemoteNG/App/Update/AppUpdater.cs +++ b/mRemoteNG/App/Update/AppUpdater.cs @@ -2,11 +2,13 @@ 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; @@ -22,29 +24,43 @@ namespace mRemoteNG.App.Update public class AppUpdater { private WebProxy _webProxy; - private Thread _getUpdateInfoThread; - private Thread _getChangeLogThread; + private HttpClient _httpClient; + // private Thread _getUpdateInfoThread; + // private Thread _getChangeLogThread; + 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; } + get + { + return changeLogCancelToken != null; + } } + /* TODO: Review later public bool IsDownloadUpdateRunning { get { return _downloadUpdateWebClient != null; } } + */ #endregion @@ -52,10 +68,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 +94,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,6 +114,7 @@ namespace mRemoteNG.App.Update return CurrentUpdateInfo.Version > GeneralAppInfo.GetApplicationVersion(); } + /* public void GetUpdateInfoAsync() { if (IsGetUpdateInfoRunning) @@ -109,7 +127,7 @@ namespace mRemoteNG.App.Update _getUpdateInfoThread.IsBackground = true; _getUpdateInfoThread.Start(); } - + public void GetChangeLogAsync() { if (CurrentUpdateInfo == null || !CurrentUpdateInfo.IsValid) @@ -128,10 +146,11 @@ namespace mRemoteNG.App.Update _getChangeLogThread.IsBackground = true; _getChangeLogThread.Start(); } + */ - public void DownloadUpdateAsync() + public async Task DownloadUpdateAsync() { - if (_downloadUpdateWebClient != null) + if (IsGetUpdateInfoRunning) { throw new InvalidOperationException("A previous call to DownloadUpdateAsync() is still in progress."); } @@ -160,17 +179,16 @@ namespace mRemoteNG.App.Update return; } #endif - DownloadUpdateWebClient.DownloadFileAsync(CurrentUpdateInfo.DownloadAddress, - CurrentUpdateInfo.UpdateFilePath); + // TODO: DownloadUpdateWebClient.DownloadFileAsync(CurrentUpdateInfo.DownloadAddress, CurrentUpdateInfo.UpdateFilePath); } #endregion #region Private Properties - private WebClient _downloadUpdateWebClient; - - private WebClient DownloadUpdateWebClient + /* + TODO: Review this part + private HttpClient DownloadUpdateWebClient { get { @@ -179,27 +197,38 @@ namespace mRemoteNG.App.Update return _downloadUpdateWebClient; } - _downloadUpdateWebClient = CreateWebClient(); + _downloadUpdateWebClient = CreateHttpClient(); - _downloadUpdateWebClient.DownloadProgressChanged += DownloadUpdateProgressChanged; - _downloadUpdateWebClient.DownloadFileCompleted += DownloadUpdateCompleted; + // TODO: _downloadUpdateWebClient.DownloadProgressChanged += DownloadUpdateProgressChanged; + // TODO: _downloadUpdateWebClient.DownloadFileCompleted += DownloadUpdateCompleted; return _downloadUpdateWebClient; } } + */ #endregion #region Private Methods - private WebClient CreateWebClient() + private void UpdateHttpClient() { - var webClient = new WebClient(); - webClient.Headers.Add("user-agent", GeneralAppInfo.UserAgent); - webClient.Proxy = _webProxy; - return webClient; + if (_httpClient != null) + { + _httpClient.Dispose(); + } + + var httpClientHandler = new HttpClientHandler(); + if (_webProxy != null) + { + httpClientHandler.UseProxy = true; + httpClientHandler.Proxy = _webProxy; + } + _httpClient = new HttpClient(httpClientHandler); + _httpClient.DefaultRequestHeaders.UserAgent.ParseAdd(GeneralAppInfo.UserAgent); } + /* TODO: Review this part private static DownloadStringCompletedEventArgs NewDownloadStringCompletedEventArgs(string result, Exception exception, bool cancelled, @@ -216,16 +245,16 @@ namespace mRemoteNG.App.Update 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); + result = httpClient.GetStringAsync(address).Result; } catch (ThreadAbortException) { @@ -238,49 +267,65 @@ namespace mRemoteNG.App.Update return NewDownloadStringCompletedEventArgs(result, exception, cancelled, null); } + */ - private void GetUpdateInfo() + public async Task GetUpdateInfoAsync() { - var e = DownloadString(UpdateChannelInfo.GetUpdateChannelInfo()); - - if (!e.Cancelled && e.Error == null) + if (IsGetUpdateInfoRunning) { - 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); - } + getUpdateInfoCancelToken.Cancel(); + getUpdateInfoCancelToken.Dispose(); + getUpdateInfoCancelToken = null; } - GetUpdateInfoCompletedEventEvent?.Invoke(this, e); + 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 void GetChangeLog() + public async Task GetChangeLogAsync() { - var e = DownloadString(CurrentUpdateInfo.ChangeLogAddress); - - if (!e.Cancelled && e.Error == null) + if (IsGetChangeLogRunning) { - ChangeLog = e.Result; + changeLogCancelToken.Cancel(); + changeLogCancelToken.Dispose(); + changeLogCancelToken = null; } - GetChangeLogCompletedEventEvent?.Invoke(this, e); + try + { + changeLogCancelToken = new CancellationTokenSource(); + return await _httpClient.GetStringAsync(CurrentUpdateInfo.ChangeLogAddress, changeLogCancelToken.Token); + } + finally + { + changeLogCancelToken.Dispose(); + changeLogCancelToken = null; + } } + /* TODO private void DownloadUpdateProgressChanged(object sender, DownloadProgressChangedEventArgs e) { DownloadUpdateProgressChangedEventEvent?.Invoke(sender, e); } + */ + /* TODO private void DownloadUpdateCompleted(object sender, AsyncCompletedEventArgs e) { var raiseEventArgs = e; @@ -333,12 +378,12 @@ namespace mRemoteNG.App.Update _downloadUpdateWebClient.Dispose(); _downloadUpdateWebClient = null; - } + }*/ #endregion #region Events - + /* TODO: private AsyncCompletedEventHandler GetUpdateInfoCompletedEventEvent; public event AsyncCompletedEventHandler GetUpdateInfoCompletedEvent @@ -404,7 +449,7 @@ namespace mRemoteNG.App.Update (AsyncCompletedEventHandler)Delegate.Remove(DownloadUpdateCompletedEventEvent, value); } } - + */ #endregion } } \ No newline at end of file diff --git a/mRemoteNG/UI/Forms/OptionsPages/UpdatesPage.cs b/mRemoteNG/UI/Forms/OptionsPages/UpdatesPage.cs index 4e336e544..d269b31e6 100644 --- a/mRemoteNG/UI/Forms/OptionsPages/UpdatesPage.cs +++ b/mRemoteNG/UI/Forms/OptionsPages/UpdatesPage.cs @@ -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,13 +208,27 @@ namespace mRemoteNG.UI.Forms.OptionsPages (int)numProxyPort.Value, chkUseProxyAuthentication.Checked, txtProxyUsername.Text, txtProxyPassword.Text); + try + { + btnTestProxy.Enabled = false; + btnTestProxy.Text = Language.OptionsProxyTesting; - btnTestProxy.Enabled = false; - btnTestProxy.Text = Language.OptionsProxyTesting; + await _appUpdate.GetUpdateInfoAsync(); - _appUpdate.GetUpdateInfoCompletedEvent += GetUpdateInfoCompleted; + btnTestProxy.Enabled = true; + btnTestProxy.Text = Language.TestProxy; + CTaskDialog.ShowCommandBox(this, Application.ProductName, Language.ProxyTestSucceeded, "", + Language._Ok, false); + } + catch (Exception ex) + { + CTaskDialog.ShowCommandBox(this, Application.ProductName, Language.ProxyTestFailed, + MiscTools.GetExceptionMessageRecursive(ex), "", "", "", Language._Ok, + false, + ESysIcons.Error, + 0); + } - _appUpdate.GetUpdateInfoAsync(); } private void chkUseProxyAuthentication_CheckedChanged(object sender, EventArgs e) @@ -228,46 +240,5 @@ namespace mRemoteNG.UI.Forms.OptionsPages } #endregion - - private void GetUpdateInfoCompleted(object sender, AsyncCompletedEventArgs e) - { - if (InvokeRequired) - { - AsyncCompletedEventHandler myDelegate = GetUpdateInfoCompleted; - Invoke(myDelegate, sender, e); - return; - } - - try - { - _appUpdate.GetUpdateInfoCompletedEvent -= GetUpdateInfoCompleted; - - 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); - } - catch (Exception ex) - { - CTaskDialog.ShowCommandBox(this, Application.ProductName, Language.ProxyTestFailed, - MiscTools.GetExceptionMessageRecursive(ex), "", "", "", Language._Ok, - false, - ESysIcons.Error, - 0); - } - } - - #endregion } } \ No newline at end of file diff --git a/mRemoteNG/UI/Forms/frmMain.cs b/mRemoteNG/UI/Forms/frmMain.cs index a05b7d7e7..05642c5ad 100644 --- a/mRemoteNG/UI/Forms/frmMain.cs +++ b/mRemoteNG/UI/Forms/frmMain.cs @@ -339,7 +339,7 @@ namespace mRemoteNG.UI.Forms } } - private void frmMain_Shown(object sender, EventArgs e) + private async void frmMain_Shown(object sender, EventArgs e) { PromptForUpdatesPreference(); CheckForUpdates(); @@ -374,7 +374,7 @@ namespace mRemoteNG.UI.Forms } } - private void CheckForUpdates() + private async void CheckForUpdates() { if (!Settings.Default.CheckForUpdatesOnStartup) return; diff --git a/mRemoteNG/UI/Window/UpdateWindow.cs b/mRemoteNG/UI/Window/UpdateWindow.cs index 0d0da2214..104cc0111 100644 --- a/mRemoteNG/UI/Window/UpdateWindow.cs +++ b/mRemoteNG/UI/Window/UpdateWindow.cs @@ -38,7 +38,7 @@ 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; @@ -97,7 +97,7 @@ namespace mRemoteNG.UI.Window #region Private Methods - private void CheckForUpdate() + private async void CheckForUpdate() { if (_appUpdate == null) { @@ -119,39 +119,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 +150,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(); } @@ -200,7 +183,7 @@ namespace mRemoteNG.UI.Window Runtime.MessageCollector?.AddExceptionStackTrace(Language.UpdateCheckCompleteFailed, ex); } } - + private void SetVisibilityOfUpdateControls(bool visible) { lblChangeLogLabel.Visible = visible; @@ -209,32 +192,6 @@ 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() { try @@ -245,8 +202,8 @@ namespace mRemoteNG.UI.Window if (_isUpdateDownloadHandlerDeclared == false) { - _appUpdate.DownloadUpdateProgressChangedEvent += DownloadUpdateProgressChanged; - _appUpdate.DownloadUpdateCompletedEvent += DownloadUpdateCompleted; + // _appUpdate.DownloadUpdateProgressChangedEvent += DownloadUpdateProgressChanged; + // _appUpdate.DownloadUpdateCompletedEvent += DownloadUpdateCompleted; _isUpdateDownloadHandlerDeclared = true; } @@ -262,6 +219,7 @@ namespace mRemoteNG.UI.Window #region Events + private void DownloadUpdateProgressChanged(object sender, DownloadProgressChangedEventArgs e) { prgbDownload.Value = e.ProgressPercentage;