Cache assembly fetches/resolution so that repeat errors aren't clogging the log
This commit is contained in:
parent
b979b6ddad
commit
d1bb921346
@ -80,53 +80,71 @@ namespace LibationFileManager
|
|||||||
return appName;
|
return appName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Use this method to locate dependencies when they are not in Libation's program files directory.
|
* Use this method to locate dependencies when they are not in Libation's program files directory.
|
||||||
*
|
*
|
||||||
private static List<ProcessModule> LoadModuleList(string exeName)
|
private static List<ProcessModule> LoadModuleList(string exeName)
|
||||||
{
|
{
|
||||||
var proc = new Process
|
var proc = new Process
|
||||||
{
|
{
|
||||||
StartInfo = new()
|
StartInfo = new()
|
||||||
{
|
{
|
||||||
FileName = exeName,
|
FileName = exeName,
|
||||||
RedirectStandardInput = true,
|
RedirectStandardInput = true,
|
||||||
RedirectStandardOutput = true,
|
RedirectStandardOutput = true,
|
||||||
CreateNoWindow = true,
|
CreateNoWindow = true,
|
||||||
WindowStyle = ProcessWindowStyle.Hidden,
|
WindowStyle = ProcessWindowStyle.Hidden,
|
||||||
UseShellExecute = false
|
UseShellExecute = false
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var waitHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
|
var waitHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
|
||||||
|
|
||||||
proc.OutputDataReceived += (_, _) => waitHandle.Set();
|
proc.OutputDataReceived += (_, _) => waitHandle.Set();
|
||||||
proc.Start();
|
proc.Start();
|
||||||
proc.BeginOutputReadLine();
|
proc.BeginOutputReadLine();
|
||||||
|
|
||||||
//Let the win process know we're ready to receive its standard output
|
//Let the win process know we're ready to receive its standard output
|
||||||
proc.StandardInput.WriteLine();
|
proc.StandardInput.WriteLine();
|
||||||
|
|
||||||
if (!waitHandle.WaitOne(2000))
|
if (!waitHandle.WaitOne(2000))
|
||||||
throw new Exception("Failed to start program");
|
throw new Exception("Failed to start program");
|
||||||
|
|
||||||
//The win process has finished loading and is now waiting inside Main().
|
//The win process has finished loading and is now waiting inside Main().
|
||||||
//Copy it process module list.
|
//Copy it process module list.
|
||||||
var modules = proc.Modules.Cast<ProcessModule>().ToList();
|
var modules = proc.Modules.Cast<ProcessModule>().ToList();
|
||||||
|
|
||||||
//Let the win process know we're done reading its module list
|
//Let the win process know we're done reading its module list
|
||||||
proc.StandardInput.WriteLine();
|
proc.StandardInput.WriteLine();
|
||||||
|
|
||||||
return modules;
|
return modules;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
private static Dictionary<string, Assembly> lowEffortCache { get; } = new();
|
||||||
private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
|
private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
|
||||||
{
|
{
|
||||||
// e.g. "System.Windows.Forms, Version=6.0.2.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
|
// e.g. "System.Windows.Forms, Version=6.0.2.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
|
||||||
var asmName = args.Name.Split(',')[0] + ".dll";
|
var asmName = args.Name.Split(',')[0] + ".dll";
|
||||||
|
var here = Path.GetDirectoryName(Environment.ProcessPath);
|
||||||
|
|
||||||
|
var key = $"{asmName}|{here}";
|
||||||
|
|
||||||
|
if (lowEffortCache.TryGetValue(key, out var value))
|
||||||
|
return value;
|
||||||
|
|
||||||
|
var assembly = CurrentDomain_AssemblyResolve_internal(asmName: asmName, here: here);
|
||||||
|
lowEffortCache[key] = assembly;
|
||||||
|
|
||||||
|
//Let the runtime handle any dll not found exceptions.
|
||||||
|
if (assembly is null)
|
||||||
|
Serilog.Log.Logger.Error($"Unable to load module {args.Name}");
|
||||||
|
|
||||||
|
return assembly;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Assembly CurrentDomain_AssemblyResolve_internal(string asmName, string here)
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* Commented code used to locate assemblies from the *ConfigApp.exe's module list.
|
* 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.
|
* Use this method to locate dependencies when they are not in Libation's program files directory.
|
||||||
@ -135,20 +153,15 @@ namespace LibationFileManager
|
|||||||
var modulePath = ModuleList.SingleOrDefault(m => m.ModuleName.EqualsInsensitive(asmName))?.FileName;
|
var modulePath = ModuleList.SingleOrDefault(m => m.ModuleName.EqualsInsensitive(asmName))?.FileName;
|
||||||
#else
|
#else
|
||||||
*/
|
*/
|
||||||
var here = Path.GetDirectoryName(Environment.ProcessPath);
|
|
||||||
|
|
||||||
// find the requested assembly in the program files directory
|
// find the requested assembly in the program files directory
|
||||||
var modulePath =
|
var modulePath =
|
||||||
Directory.EnumerateFiles(here, asmName, SearchOption.TopDirectoryOnly)
|
Directory.EnumerateFiles(here, asmName, SearchOption.TopDirectoryOnly)
|
||||||
.SingleOrDefault();
|
.SingleOrDefault();
|
||||||
|
|
||||||
//#endif
|
//#endif
|
||||||
if (modulePath is null)
|
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 null;
|
||||||
}
|
|
||||||
|
|
||||||
return Assembly.LoadFrom(modulePath);
|
return Assembly.LoadFrom(modulePath);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user