From 8631c3df37b588e451d599265a7edcfaef3d1578 Mon Sep 17 00:00:00 2001 From: ced777ric <44529860+ced777ric@users.noreply.github.com> Date: Wed, 30 Nov 2022 08:18:15 -0800 Subject: [PATCH] Dependency check does not take plugins that embed dependencies into account. (#52) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * try loading first, then check for missing dependencies so plugins that have them embedded can be loaded * print errors if dependencies match * resolve embedded resources * docs * Update NwPluginAPI/Loader/AssemblyLoader.cs Co-authored-by: Łukasz Jurczyk * Update NwPluginAPI/Loader/AssemblyLoader.cs Co-authored-by: Łukasz Jurczyk Co-authored-by: Łukasz Jurczyk --- NwPluginAPI/Loader/AssemblyLoader.cs | 90 ++++++++++++++++++++++++---- 1 file changed, 77 insertions(+), 13 deletions(-) diff --git a/NwPluginAPI/Loader/AssemblyLoader.cs b/NwPluginAPI/Loader/AssemblyLoader.cs index 768c831..22e5646 100644 --- a/NwPluginAPI/Loader/AssemblyLoader.cs +++ b/NwPluginAPI/Loader/AssemblyLoader.cs @@ -1,5 +1,6 @@ namespace PluginAPI.Loader { + using System.IO.Compression; using System; using System.Collections.Generic; using System.IO; @@ -124,19 +125,31 @@ private static void LoadPlugins(PluginDirectory directory) if (!TryGetAssembly(pluginPath, out Assembly assembly)) continue; - var missingDependencies = assembly - .GetReferencedAssemblies() - .Select(x => - $"{x.Name}&r v&6{x.Version.ToString(3)}") - .Where(x => !loadedAssemblies.Contains(x)).ToArray(); - - if (missingDependencies.Length != 0) - { - Log.Error($"Failed loading plugin &2{Path.GetFileNameWithoutExtension(pluginPath)}&r, missing dependencies\n&2{string.Join("\n", missingDependencies.Select(x => $"&r - &2{x}&r"))}", "Loader"); - continue; - } - - var types = assembly.GetTypes(); + Type[] types = null; + + var missingDependencies = assembly + .GetReferencedAssemblies() + .Select(x => + $"{x.Name}&r v&6{x.Version.ToString(3)}") + .Where(x => !loadedAssemblies.Contains(x)).ToArray(); + + try + { + if (missingDependencies.Length != 0) + ResolveAssemblyEmbeddedResources(assembly); + types = assembly.GetTypes(); + } + catch (Exception e) + { + if (missingDependencies.Length != 0) + { + Log.Error($"Failed loading plugin &2{Path.GetFileNameWithoutExtension(pluginPath)}&r, missing dependencies\n&2{string.Join("\n", missingDependencies.Select(x => $"&r - &2{x}&r"))}\n\n{e}", "Loader"); + continue; + } + + Log.Error($"Failed loading plugin &2{Path.GetFileNameWithoutExtension(pluginPath)}&r, {e.ToString()}"); + continue; + } foreach (var entryType in types) { @@ -226,5 +239,56 @@ private static bool TryGetAssembly(string path, out Assembly assembly) assembly = null; return false; } + + /// + /// Attempts to load Embedded assemblies (compressed) from the target + /// + /// Assembly to check for embedded assemblies + private static void ResolveAssemblyEmbeddedResources(Assembly target) + { + Log.Debug($"Attempting to load embedded resources for {target.FullName}", Log.DebugMode); + + + var resourceNames = target.GetManifestResourceNames(); + foreach (var name in resourceNames) + { + Log.Debug($"Found {name}", Log.DebugMode); + if (name.EndsWith(".dll", StringComparison.OrdinalIgnoreCase)) + { + using (MemoryStream stream = new MemoryStream()) + { + Log.Debug($"Loading {name}", Log.DebugMode); + var dataStream = target.GetManifestResourceStream(name); + if (dataStream == null) + { + Log.Error($"Unable to resolve {name} Stream was null"); + continue; + } + + dataStream.CopyTo(stream); + Assembly.Load(stream.ToArray()); + Log.Debug($"Loaded {name}", Log.DebugMode); + } + } + else if (name.EndsWith(".dll.compressed", StringComparison.OrdinalIgnoreCase)) + { + var dataStream = target.GetManifestResourceStream(name); + if (dataStream == null) + { + Log.Error($"Unable to resolve {name} Stream was null"); + continue; + } + + using (DeflateStream stream = new DeflateStream(dataStream, CompressionMode.Decompress)) + using (MemoryStream memStream = new MemoryStream()) + { + Log.Debug($"Loading {name}", Log.DebugMode); + stream.CopyTo(memStream); + Assembly.Load(memStream.ToArray()); + Log.Debug($"Loaded {name}", Log.DebugMode); + } + } + } + } } }