diff --git a/Source/LibationFileManager/InteropFactory.cs b/Source/LibationFileManager/InteropFactory.cs index d596c9ab..b05919c9 100644 --- a/Source/LibationFileManager/InteropFactory.cs +++ b/Source/LibationFileManager/InteropFactory.cs @@ -80,53 +80,71 @@ namespace LibationFileManager return appName; } - /* - * Use this method to locate dependencies when they are not in Libation's program files directory. - * - private static List LoadModuleList(string exeName) - { - var proc = new Process - { - StartInfo = new() - { - FileName = exeName, - RedirectStandardInput = true, - RedirectStandardOutput = true, - CreateNoWindow = true, - WindowStyle = ProcessWindowStyle.Hidden, - UseShellExecute = false - } - }; + /* + * Use this method to locate dependencies when they are not in Libation's program files directory. + * + private static List LoadModuleList(string exeName) + { + var proc = new Process + { + StartInfo = new() + { + FileName = exeName, + RedirectStandardInput = true, + RedirectStandardOutput = true, + CreateNoWindow = true, + WindowStyle = ProcessWindowStyle.Hidden, + UseShellExecute = false + } + }; - var waitHandle = new EventWaitHandle(false, EventResetMode.ManualReset); + var waitHandle = new EventWaitHandle(false, EventResetMode.ManualReset); - proc.OutputDataReceived += (_, _) => waitHandle.Set(); - proc.Start(); - proc.BeginOutputReadLine(); + proc.OutputDataReceived += (_, _) => waitHandle.Set(); + proc.Start(); + proc.BeginOutputReadLine(); - //Let the win process know we're ready to receive its standard output - proc.StandardInput.WriteLine(); + //Let the win process know we're ready to receive its standard output + proc.StandardInput.WriteLine(); - if (!waitHandle.WaitOne(2000)) - throw new Exception("Failed to start program"); + if (!waitHandle.WaitOne(2000)) + throw new Exception("Failed to start program"); - //The win process has finished loading and is now waiting inside Main(). - //Copy it process module list. - var modules = proc.Modules.Cast().ToList(); + //The win process has finished loading and is now waiting inside Main(). + //Copy it process module list. + var modules = proc.Modules.Cast().ToList(); - //Let the win process know we're done reading its module list - proc.StandardInput.WriteLine(); + //Let the win process know we're done reading its module list + proc.StandardInput.WriteLine(); - return modules; - } - */ + return modules; + } + */ + private static Dictionary lowEffortCache { get; } = new(); 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] + ".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. * 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; #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 +//#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); }