Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace WebClient with HttpClient #1908

Merged
merged 3 commits into from
Dec 2, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
194 changes: 95 additions & 99 deletions UndertaleModTool/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3084,6 +3084,8 @@ public async void UpdateApp(SettingsWindow window)
string tempFolder = Path.Combine(Path.GetTempPath(), "UndertaleModTool");
Directory.CreateDirectory(tempFolder); // We're about to download, so make sure the download dir actually exists

string downloadOutput = Path.Combine(tempFolder, "Update.zip.zip");

// It's time to download; let's use a cool progress bar
scriptDialog = new("Downloading", "Downloading new version...")
{
Expand All @@ -3093,135 +3095,129 @@ public async void UpdateApp(SettingsWindow window)
};
SetProgressBar();

using (WebClient webClient = new())
try
{
bool end = false;
bool ended = false;
string downloaded = "0.00";

webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler((sender, e) =>
{
if (!end)
downloaded = (e.BytesReceived / bytesToMB).ToString("F2", CultureInfo.InvariantCulture);
});
webClient.DownloadFileCompleted += new AsyncCompletedEventHandler((sender, e) =>
_ = Task.Run(async () =>
{
end = true;

HideProgressBar();
_ = Task.Run(() =>
using (HttpClient httpClient = new() { Timeout = TimeSpan.FromMinutes(5) })
{
// wait until progress bar updater loop is finished
while (!ended)
Thread.Sleep(100);

scriptDialog = null;
});

if (e.Error is not null)
{
string errMsg;

if (e.Error.InnerException?.InnerException is Exception ex)
// Read HTTP response
using (HttpResponseMessage response = await httpClient.GetAsync(new Uri(downloadUrl), HttpCompletionOption.ResponseHeadersRead))
{
if (ex.Message.StartsWith("Unable to read data")
&& e.Error.InnerException.Message.StartsWith("The SSL connection could not be established"))
// Read header
response.EnsureSuccessStatusCode();
long totalBytes = response.Content.Headers.ContentLength ?? throw new Exception("Missing content length");

// Start reading content
using Stream contentStream = await response.Content.ReadAsStreamAsync();
const int downloadBufferSize = 8192;
byte[] downloadBuffer = new byte[downloadBufferSize];

// Download content and save to file
using FileStream fs = new(downloadOutput, FileMode.Create, FileAccess.Write, FileShare.None, downloadBufferSize, true);
int bytesRead = await contentStream.ReadAsync(downloadBuffer);
long totalBytesDownloaded = 0;
long bytesToUpdateProgress = totalBytes / 500;
long bytesToProgressCounter = 0;
while (bytesRead > 0)
{
errMsg = "Failed to download new version of UndertaleModTool.\n" +
"Error - The SSL connection could not be established.";

bool isWin7 = Environment.OSVersion.Version.Major == 6;
string win7upd = "\nProbably, you need to install Windows update KB2992611.\n" +
"Open the update download page?";
// Write current data to file
await fs.WriteAsync(downloadBuffer.AsMemory(0, bytesRead));

if (isWin7)
// Update progress
totalBytesDownloaded += bytesRead;
bytesToProgressCounter += bytesRead;
if (bytesToProgressCounter >= bytesToUpdateProgress)
{
if (this.ShowQuestion(errMsg + win7upd, MessageBoxImage.Error) == MessageBoxResult.Yes)
OpenBrowser("https://www.microsoft.com/en-us/download/details.aspx?id=44622");

window.UpdateButtonEnabled = true;
return;
bytesToProgressCounter -= bytesToUpdateProgress;
UpdateProgressStatus($"Downloaded MB: {(totalBytesDownloaded / bytesToMB).ToString("F2", CultureInfo.InvariantCulture)}");
}

// Read next bytes
bytesRead = await contentStream.ReadAsync(downloadBuffer);
}
else
errMsg = ex.Message;
}
else if (e.Error.InnerException is Exception ex1)
errMsg = ex1.Message;
else
errMsg = e.Error.Message;

this.ShowError($"Failed to download new version of UndertaleModTool.\nError - {errMsg}.");
window.UpdateButtonEnabled = true;
return;
}

// Unzip double-zipped update
ZipFile.ExtractToDirectory(Path.Combine(tempFolder, "Update.zip.zip"), tempFolder, true);
File.Move(Path.Combine(tempFolder, $"{patchName}.zip"), Path.Combine(tempFolder, "Update.zip"), true);
File.Delete(Path.Combine(tempFolder, "Update.zip.zip"));

string updaterFolder = Path.Combine(ExePath, "Updater");
if (!File.Exists(Path.Combine(updaterFolder, "UndertaleModToolUpdater.exe")))
{
this.ShowError("Updater not found! Aborting update, report this to the devs!\nLocation checked: " + updaterFolder);
window.UpdateButtonEnabled = true;
return;
}
// Download complete, hide progress bar
HideProgressBar();

// Extract ZIP
string updaterFolderTemp = Path.Combine(tempFolder, "Updater");
bool extractedSuccessfully = false;
try
{
if (Directory.Exists(updaterFolderTemp))
Directory.Delete(updaterFolderTemp, true);
// Unzip double-zipped update
ZipFile.ExtractToDirectory(downloadOutput, tempFolder, true);
File.Move(Path.Combine(tempFolder, $"{patchName}.zip"), Path.Combine(tempFolder, "Update.zip"), true);
File.Delete(downloadOutput);

Directory.CreateDirectory(updaterFolderTemp);
foreach (string file in Directory.GetFiles(updaterFolder))
string updaterFolder = Path.Combine(ExePath, "Updater");
if (!File.Exists(Path.Combine(updaterFolder, "UndertaleModToolUpdater.exe")))
{
File.Copy(file, Path.Combine(updaterFolderTemp, Path.GetFileName(file)));
this.ShowError("Updater not found! Aborting update, report this to the devs!\nLocation checked: " + updaterFolder);
return;
}
}
catch (Exception ex)
{
this.ShowError($"Can't copy the updater app to the temporary folder.\n{ex}");
window.UpdateButtonEnabled = true;
return;
}
File.WriteAllText(Path.Combine(updaterFolderTemp, "actualAppFolder"), ExePath);

window.UpdateButtonEnabled = true;
try
{
if (Directory.Exists(updaterFolderTemp))
Directory.Delete(updaterFolderTemp, true);

this.ShowMessage("UndertaleModTool will now close to finish the update.");
Directory.CreateDirectory(updaterFolderTemp);
foreach (string file in Directory.GetFiles(updaterFolder))
{
File.Copy(file, Path.Combine(updaterFolderTemp, Path.GetFileName(file)));
}
}
catch (Exception ex)
{
this.ShowError($"Can't copy the updater app to the temporary folder.\n{ex}");
return;
}
File.WriteAllText(Path.Combine(updaterFolderTemp, "actualAppFolder"), ExePath);

Process.Start(new ProcessStartInfo(Path.Combine(updaterFolderTemp, "UndertaleModToolUpdater.exe"))
extractedSuccessfully = true;
}
finally
{
WorkingDirectory = updaterFolderTemp
});

CloseOtherWindows();

Closing -= DataWindow_Closing; // disable "on window closed" event handler
Close();
});
// If we return early or not, always update button status
Dispatcher.Invoke(() =>
{
window.UpdateButtonEnabled = !extractedSuccessfully;
});
}

_ = Task.Run(() =>
{
while (!end)
// Move back to UI thread to perform final actions
Dispatcher.Invoke(() =>
{
try
this.ShowMessage("UndertaleModTool will now close to finish the update.");

// Invoke updater
Process.Start(new ProcessStartInfo(Path.Combine(updaterFolderTemp, "UndertaleModToolUpdater.exe"))
{
UpdateProgressStatus($"Downloaded MB: {downloaded}");
}
catch {}
WorkingDirectory = updaterFolderTemp
});

Thread.Sleep(100);
}
CloseOtherWindows();

ended = true;
Closing -= DataWindow_Closing; // disable "on window closed" event handler
Close();
});
});
}
catch (Exception e)
{
string errMsg;
if (e.InnerException?.InnerException is Exception ex)
errMsg = ex.Message;
else if (e.InnerException is Exception ex1)
errMsg = ex1.Message;
else
errMsg = e.Message;

// The Artifact is already zipped then zipped again by the download archive
webClient.DownloadFileAsync(new Uri(downloadUrl), Path.Combine(tempFolder, "Update.zip.zip"));
this.ShowError($"Failed to download new version of UndertaleModTool.\nError - {errMsg}.");
window.UpdateButtonEnabled = true;
}
}

Expand Down
Loading