Compare commits

...

9 Commits

Author SHA1 Message Date
Robert McRackan
f310d583d8 Bug fix #364 - app was crashing on attempt to download PDF to which the user no longer had ownership. Eg: returned or Plus catalog 2022-08-29 15:05:56 -04:00
Robert McRackan
f05465b29b incr ver 2022-08-18 13:38:23 -04:00
rmcrackan
959e31972e Merge pull request #363 from Mbucari/master
Change assembly loadig
2022-08-18 13:36:08 -04:00
Michael Bucari-Tovo
17181811f0 Remove assembly hot loading 2022-08-18 11:21:40 -06:00
Michael Bucari-Tovo
6d2624d52b Fix comment 2022-08-18 10:59:37 -06:00
Michael Bucari-Tovo
9dd5940c8c Remove trailing wild 2022-08-18 10:59:00 -06:00
Michael Bucari-Tovo
1927d19961 comments 2022-08-18 10:47:53 -06:00
Michael Bucari-Tovo
09cc838bb4 Checks 2022-08-18 10:45:07 -06:00
Michael Bucari-Tovo
8af4c71101 Change assembly loadig 2022-08-18 10:29:30 -06:00
5 changed files with 130 additions and 67 deletions

View File

@@ -2,7 +2,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Version>8.4.2.1</Version>
<Version>8.4.4.1</Version>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Octokit" Version="2.0.0" />

View File

@@ -24,7 +24,7 @@ namespace FileLiberator
{
OnBegin(libraryBook);
try
try
{
var proposedDownloadFilePath = getProposedDownloadFilePath(libraryBook);
var actualDownloadedFilePath = await downloadPdfAsync(libraryBook, proposedDownloadFilePath);
@@ -32,13 +32,22 @@ namespace FileLiberator
libraryBook.Book.UpdatePdfStatus(result.IsSuccess ? LiberatedStatus.Liberated : LiberatedStatus.NotLiberated);
return result;
}
return result;
}
catch (Exception ex)
{
Serilog.Log.Logger.Error(ex, "Error downloading PDF");
var result = new StatusHandler();
result.AddError($"Error downloading PDF. See log for details. Error summary: {ex.Message}");
return result;
}
finally
{
OnCompleted(libraryBook);
}
}
}
}
private static string getProposedDownloadFilePath(LibraryBook libraryBook)
{

View File

@@ -7,6 +7,7 @@ using Avalonia.Media;
using Avalonia.Media.Imaging;
using DataLayer;
using Dinah.Core;
using Dinah.Core.ErrorHandling;
using FileLiberator;
using LibationFileManager;
using ReactiveUI;
@@ -289,25 +290,36 @@ namespace LibationAvalonia.ViewModels
Logger.Info($"{((Processable)sender).Name} Step, Completed: {libraryBook.Book}");
UnlinkProcessable((Processable)sender);
if (Processes.Count > 0)
{
NextProcessable();
LinkProcessable(CurrentProcessable);
var result = await CurrentProcessable.ProcessSingleAsync(libraryBook, validate: true);
if (Processes.Count == 0)
{
Completed?.Invoke(this, EventArgs.Empty);
return;
}
if (result.HasErrors)
{
foreach (var errorMessage in result.Errors.Where(e => e != "Validation failed"))
Logger.Error(errorMessage);
NextProcessable();
LinkProcessable(CurrentProcessable);
Completed?.Invoke(this, EventArgs.Empty);
}
}
else
StatusHandler result;
try
{
Completed?.Invoke(this, EventArgs.Empty);
}
}
result = await CurrentProcessable.ProcessSingleAsync(libraryBook, validate: true);
}
catch (Exception ex)
{
Serilog.Log.Logger.Error(ex, $"{nameof(Processable_Completed)} error");
result = new StatusHandler();
result.AddError($"{nameof(Processable_Completed)} error. See log for details. Error summary: {ex.Message}");
}
if (result.HasErrors)
{
foreach (var errorMessage in result.Errors.Where(e => e != "Validation failed"))
Logger.Error(errorMessage);
Completed?.Invoke(this, EventArgs.Empty);
}
}
#endregion

View File

@@ -21,7 +21,7 @@ namespace LibationFileManager
private static IInteropFunctions _create(params object[] values)
=> InteropFunctionsType is null ? new NullInteropFunctions()
//: values is null || values.Length == 0 ? Activator.CreateInstance(InteropFunctionsType) as IInteropFunctions
//: values is null || values.Length == 0 ? Activator.CreateInstance(InteropFunctionsType) as IInteropFunctions
: Activator.CreateInstance(InteropFunctionsType, values) as IInteropFunctions;
#region load types
@@ -32,7 +32,7 @@ namespace LibationFileManager
: Configuration.IsMacOs ? a => Path.GetFileName(a).StartsWithInsensitive("mac") || Path.GetFileName(a).StartsWithInsensitive("osx")
: _ => false;
private const string CONFIG_APP_ENDING = "ConfigApp.exe";
private const string CONFIG_APP_ENDING = "ConfigApp.dll";
private static List<ProcessModule> ModuleList { get; } = new();
static InteropFactory()
{
@@ -41,16 +41,26 @@ namespace LibationFileManager
// nothing to load
if (configApp is null)
{
Serilog.Log.Logger.Error($"Unable to locate *{CONFIG_APP_ENDING}");
return;
}
// runs the exe and gets the exe's loaded modules
ModuleList = LoadModuleList(Path.GetFileNameWithoutExtension(configApp))
.OrderBy(x => x.ModuleName)
.ToList();
/*
* Commented code used to locate assemblies from the *ConfigApp.exe's module list.
* Use this method to locate dependencies when they are not in Libation's program files directory.
#if DEBUG
// runs the exe and gets the exe's loaded modules
ModuleList = LoadModuleList(Path.GetFileNameWithoutExtension(configApp))
.OrderBy(x => x.ModuleName)
.ToList();
#endif
*/
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
var configAppAssembly = Assembly.LoadFrom(Path.ChangeExtension(configApp, "dll"));
var configAppAssembly = Assembly.LoadFrom(configApp);
var type = typeof(IInteropFunctions);
InteropFunctionsType = configAppAssembly
.GetTypes()
@@ -60,21 +70,19 @@ namespace LibationFileManager
{
var here = Path.GetDirectoryName(Environment.ProcessPath);
// find '*ConfigApp.exe' files
var exes =
// find '*ConfigApp.dll' files
var appName =
Directory.EnumerateFiles(here, $"*{CONFIG_APP_ENDING}", SearchOption.TopDirectoryOnly)
// sanity check. shouldn't ever be true
.Except(new[] { Environment.ProcessPath })
.Where(exe =>
// has a corresponding dll
File.Exists(Path.ChangeExtension(exe, "dll"))
&& MatchesOS(exe)
)
.ToList();
var exeName = exes.FirstOrDefault();
return exeName;
.FirstOrDefault(exe => MatchesOS(exe));
return appName;
}
/*
* Use this method to locate dependencies when they are not in Libation's program files directory.
*
private static List<ProcessModule> LoadModuleList(string exeName)
{
var proc = new Process
@@ -111,16 +119,38 @@ namespace LibationFileManager
return modules;
}
*/
private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
// e.g. "System.Windows.Forms, Version=6.0.2.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
var asmName = args.Name.Split(',')[0];
var asmName = args.Name.Split(',')[0] + ".dll";
// `First` instead of `FirstOrDefault`. If it's not present we're going to fail anyway. May as well be here
var module = ModuleList.First(m => m.ModuleName.StartsWith(asmName));
return Assembly.LoadFrom(module.FileName);
/*
* Commented code used to locate assemblies from the *ConfigApp.exe's module list.
* Use this method to locate dependencies when they are not in Libation's program files directory.
#if DEBUG
var modulePath = ModuleList.SingleOrDefault(m => m.ModuleName.EqualsInsensitive(asmName))?.FileName;
#else
*/
var here = Path.GetDirectoryName(Environment.ProcessPath);
// find the requested assembly in the program files directory
var modulePath =
Directory.EnumerateFiles(here, asmName, SearchOption.TopDirectoryOnly)
.SingleOrDefault();
//#endif
if (modulePath is null)
{
//Let the runtime handle any dll not found exceptions.
Serilog.Log.Logger.Error($"Unable to load module {args.Name}");
return null;
}
return Assembly.LoadFrom(modulePath);
}
#endregion

View File

@@ -9,6 +9,7 @@ using System.Windows.Forms;
using ApplicationServices;
using DataLayer;
using Dinah.Core;
using Dinah.Core.ErrorHandling;
using Dinah.Core.WindowsDesktop.Drawing;
using FileLiberator;
using LibationFileManager;
@@ -279,36 +280,47 @@ namespace LibationWinForms.ProcessQueue
updateBookInfo();
}
private async void Processable_Completed(object sender, LibraryBook libraryBook)
{
Logger.Info($"{((Processable)sender).Name} Step, Completed: {libraryBook.Book}");
UnlinkProcessable((Processable)sender);
private async void Processable_Completed(object sender, LibraryBook libraryBook)
{
Logger.Info($"{((Processable)sender).Name} Step, Completed: {libraryBook.Book}");
UnlinkProcessable((Processable)sender);
if (Processes.Count > 0)
{
NextProcessable();
LinkProcessable(CurrentProcessable);
var result = await CurrentProcessable.ProcessSingleAsync(libraryBook, validate: true);
if (Processes.Count == 0)
{
Completed?.Invoke(this, EventArgs.Empty);
return;
}
if (result.HasErrors)
{
foreach (var errorMessage in result.Errors.Where(e => e != "Validation failed"))
Logger.Error(errorMessage);
NextProcessable();
LinkProcessable(CurrentProcessable);
Completed?.Invoke(this, EventArgs.Empty);
}
}
else
{
Completed?.Invoke(this, EventArgs.Empty);
}
}
StatusHandler result;
try
{
result = await CurrentProcessable.ProcessSingleAsync(libraryBook, validate: true);
}
catch (Exception ex)
{
Serilog.Log.Logger.Error(ex, $"{nameof(Processable_Completed)} error");
#endregion
result = new StatusHandler();
result.AddError($"{nameof(Processable_Completed)} error. See log for details. Error summary: {ex.Message}");
}
#region Failure Handler
if (result.HasErrors)
{
foreach (var errorMessage in result.Errors.Where(e => e != "Validation failed"))
Logger.Error(errorMessage);
private ProcessBookResult showRetry(LibraryBook libraryBook)
Completed?.Invoke(this, EventArgs.Empty);
}
}
#endregion
#region Failure Handler
private ProcessBookResult showRetry(LibraryBook libraryBook)
{
Logger.Error("ERROR. All books have not been processed. Most recent book: processing failed");