Added the progress handling;

Now API (AppUpdater) is async.
Cancellation token hasn't been tested yet, because UI doesn't allow to cancel the update.

Signed-off-by: Vest <Vest@users.noreply.github.com>
This commit is contained in:
Vest
2021-12-16 15:37:56 +01:00
parent e9fa1c3b5e
commit 2fe85ae0e5
2 changed files with 56 additions and 46 deletions

View File

@@ -148,10 +148,14 @@ namespace mRemoteNG.App.Update
}
*/
public async Task DownloadUpdateAsync()
public async Task DownloadUpdateAsync(IProgress<int> progress)
{
if (IsGetUpdateInfoRunning)
{
getUpdateInfoCancelToken.Cancel();
getUpdateInfoCancelToken.Dispose();
getUpdateInfoCancelToken = null;
throw new InvalidOperationException("A previous call to DownloadUpdateAsync() is still in progress.");
}
@@ -161,8 +165,7 @@ namespace mRemoteNG.App.Update
"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
{
@@ -179,7 +182,42 @@ namespace mRemoteNG.App.Update
return;
}
#endif
// TODO: DownloadUpdateWebClient.DownloadFileAsync(CurrentUpdateInfo.DownloadAddress, CurrentUpdateInfo.UpdateFilePath);
try
{
getUpdateInfoCancelToken = new CancellationTokenSource();
using (var response = await _httpClient.GetAsync(CurrentUpdateInfo.DownloadAddress,
HttpCompletionOption.ResponseHeadersRead, getUpdateInfoCancelToken.Token))
{
var buffer = new byte[8192];
var totalBytes = response.Content.Headers.ContentLength ?? 0;
var readBytes = 0L;
await using var httpStream =
await response.Content.ReadAsStreamAsync(getUpdateInfoCancelToken.Token);
await using var fileStream = new FileStream(CurrentUpdateInfo.UpdateFilePath, FileMode.Create,
FileAccess.Write, FileShare.None, buffer.Length, true);
while (readBytes <= totalBytes || !getUpdateInfoCancelToken.IsCancellationRequested)
{
var bytesRead = await httpStream.ReadAsync(buffer, 0, buffer.Length, getUpdateInfoCancelToken.Token);
if (bytesRead == 0)
{
progress.Report(100);
break;
}
await fileStream.WriteAsync(buffer, 0, bytesRead, getUpdateInfoCancelToken.Token);
readBytes += bytesRead;
var percentComplete = (int)(readBytes * 100 / totalBytes);
progress.Report(percentComplete);
}
}
} finally{
getUpdateInfoCancelToken.Dispose();
getUpdateInfoCancelToken = null;
}
}
#endregion

View File

@@ -11,13 +11,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
@@ -43,7 +44,7 @@ namespace mRemoteNG.UI.Window
ApplyTheme();
ThemeManager.getInstance().ThemeChanged += ApplyTheme;
ApplyLanguage();
CheckForUpdate();
CheckForUpdateAsync();
}
private new void ApplyTheme()
@@ -74,12 +75,12 @@ namespace mRemoteNG.UI.Window
private void btnCheckForUpdate_Click(object sender, EventArgs e)
{
CheckForUpdate();
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 +98,7 @@ namespace mRemoteNG.UI.Window
#region Private Methods
private async void CheckForUpdate()
private async void CheckForUpdateAsync()
{
if (_appUpdate == null)
{
@@ -192,7 +193,7 @@ namespace mRemoteNG.UI.Window
prgbDownload.Visible = visible;
}
private void DownloadUpdate()
private async Task DownloadUpdateAsync()
{
try
{
@@ -200,50 +201,18 @@ 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);
MessageBoxButtons.OK, MessageBoxIcon.Information);
else
{
if (MessageBox.Show(Language.UpdateDownloadComplete, Language.CheckForUpdates,
MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) == DialogResult.OK)
MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) == DialogResult.OK)
{
Shutdown.Quit(_appUpdate.CurrentUpdateInfo.UpdateFilePath);
}
@@ -255,8 +224,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);
}
}