oh so we're back to this huh

hopefully async exception management should be better?
This commit is contained in:
pizzaboxer 2023-07-26 01:29:06 +01:00
parent 5de6d02922
commit 102f6d1949
No known key found for this signature in database
GPG Key ID: 59D4A1DBAD0F2BA8
3 changed files with 44 additions and 24 deletions

View File

@ -67,13 +67,15 @@ namespace Bloxstrap
e.Handled = true; e.Handled = true;
Logger.WriteLine("App::GlobalExceptionHandler", "An exception occurred"); Logger.WriteLine("App::GlobalExceptionHandler", "An exception occurred");
Logger.WriteLine("App::GlobalExceptionHandler", $"{e.Exception}");
FinalizeExceptionHandling(e.Exception); FinalizeExceptionHandling(e.Exception);
} }
void FinalizeExceptionHandling(Exception exception) public static void FinalizeExceptionHandling(Exception exception, bool log = true)
{ {
if (log)
Logger.WriteException("App::FinalizeExceptionHandling", exception);
#if DEBUG #if DEBUG
throw exception; throw exception;
#else #else
@ -306,7 +308,7 @@ namespace Bloxstrap
if (t.Exception is null) if (t.Exception is null)
return; return;
Logger.WriteLine(LOG_IDENT, $"{t.Exception}"); Logger.WriteException(LOG_IDENT, t.Exception);
Exception exception = t.Exception; Exception exception = t.Exception;
@ -315,7 +317,7 @@ namespace Bloxstrap
exception = t.Exception.InnerException!; exception = t.Exception.InnerException!;
#endif #endif
FinalizeExceptionHandling(exception); FinalizeExceptionHandling(exception, false);
}); });
// this ordering is very important as all wpf windows are shown as modal dialogs, mess it up and you'll end up blocking input to one of them // this ordering is very important as all wpf windows are shown as modal dialogs, mess it up and you'll end up blocking input to one of them

View File

@ -787,7 +787,7 @@ namespace Bloxstrap
// extract the package immediately after download asynchronously // extract the package immediately after download asynchronously
// discard is just used to suppress the warning // discard is just used to suppress the warning
Task _ = ExtractPackage(package); _ = ExtractPackage(package);
} }
if (_cancelFired) if (_cancelFired)
@ -808,6 +808,7 @@ namespace Bloxstrap
await Task.Delay(100); await Task.Delay(100);
} }
App.Logger.WriteLine(LOG_IDENT, "Writing AppSettings.xml...");
string appSettingsLocation = Path.Combine(_versionFolder, "AppSettings.xml"); string appSettingsLocation = Path.Combine(_versionFolder, "AppSettings.xml");
await File.WriteAllTextAsync(appSettingsLocation, AppSettings); await File.WriteAllTextAsync(appSettingsLocation, AppSettings);
@ -1220,7 +1221,7 @@ namespace Bloxstrap
{ {
FileInfo file = new(packageLocation); FileInfo file = new(packageLocation);
string calculatedMD5 = Utility.MD5Hash.FromFile(packageLocation); string calculatedMD5 = MD5Hash.FromFile(packageLocation);
if (calculatedMD5 != package.Signature) if (calculatedMD5 != package.Signature)
{ {
@ -1292,37 +1293,34 @@ namespace Bloxstrap
string packageLocation = Path.Combine(Paths.Downloads, package.Signature); string packageLocation = Path.Combine(Paths.Downloads, package.Signature);
string packageFolder = Path.Combine(_versionFolder, PackageDirectories[package.Name]); string packageFolder = Path.Combine(_versionFolder, PackageDirectories[package.Name]);
string extractPath;
App.Logger.WriteLine(LOG_IDENT, $"Extracting {package.Name} to {packageFolder}..."); App.Logger.WriteLine(LOG_IDENT, $"Extracting {package.Name} to {packageFolder}...");
using ZipArchive archive = await Task.Run(() => ZipFile.OpenRead(packageLocation)); var readTask = new Task<ZipArchive>(() => ZipFile.OpenRead(packageLocation));
_ = readTask.ContinueWith(AsyncHelpers.ExceptionHandler, $"reading {package.Name}");
readTask.Start();
foreach (ZipArchiveEntry entry in archive.Entries) using ZipArchive archive = await readTask.WaitAsync(TimeSpan.FromSeconds(30));
// yeah so because roblox is roblox, these packages aren't actually valid zip files
// besides the fact that they use backslashes instead of forward slashes for directories,
// empty folders that *BEGIN* with a backslash in their fullname, but have an empty name are listed here for some reason...
foreach (var entry in archive.Entries)
{ {
if (_cancelFired) if (_cancelFired)
return; return;
if (entry.FullName.EndsWith('\\')) if (String.IsNullOrEmpty(entry.Name))
continue; continue;
extractPath = Path.Combine(packageFolder, entry.FullName); string extractPath = Path.Combine(packageFolder, entry.FullName);
//App.Logger.WriteLine("{package.Name}", $"Writing {extractPath}...");
string? directory = Path.GetDirectoryName(extractPath); string? directory = Path.GetDirectoryName(extractPath);
if (directory is null) if (directory is not null)
continue; Directory.CreateDirectory(directory);
Directory.CreateDirectory(directory); entry.ExtractToFile(extractPath, true);
using var fileStream = new FileStream(extractPath, FileMode.CreateNew, FileAccess.Write, FileShare.None, bufferSize: 0x1000, useAsync: true);
using var dataStream = entry.Open();
await dataStream.CopyToAsync(fileStream);
File.SetLastWriteTime(extractPath, entry.LastWriteTime.DateTime);
} }
App.Logger.WriteLine(LOG_IDENT, $"Finished extracting {package.Name}"); App.Logger.WriteLine(LOG_IDENT, $"Finished extracting {package.Name}");

View File

@ -0,0 +1,20 @@
namespace Bloxstrap.Utility
{
public static class AsyncHelpers
{
public static void ExceptionHandler(Task task, object? state)
{
const string LOG_IDENT = "AsyncHelpers::ExceptionHandler";
if (task.Exception is null)
return;
if (state is null)
App.Logger.WriteLine(LOG_IDENT, "An exception occurred while running the task");
else
App.Logger.WriteLine(LOG_IDENT, $"An exception occurred while running the task '{state}'");
App.FinalizeExceptionHandling(task.Exception);
}
}
}