internal bool InUse(DynamoModel dynamoModel) { return((LoadedAssemblies.Any() || IsWorkspaceFromPackageOpen(dynamoModel) || IsCustomNodeFromPackageInUse(dynamoModel)) && Loaded); }
//private Assembly AssemblyResolving(AssemblyLoadContext arg1, AssemblyName arg2) //{ // if (arg2.FullName == CurrentAssembly.FullName) // { // return CurrentAssembly; // } // var deps = DependencyContext.Default; // if (deps.CompileLibraries.Any(d => d.Name == arg2.Name)) // { // return Assembly.Load(arg2); // } // foreach (var item in DependencyAssemblies) // { // if (item.FullName == arg2.FullName) // { // return item; // } // } // return null; //} private void ResolveDenpendency(Assembly assembly) { string currentName = assembly.GetName().Name; if (CompileLibraries == null) { CompileLibraries = new HashSet <string>(); foreach (var item in DependencyContext.Default.CompileLibraries) { if (!CompileLibraries.Contains(item.Name)) { CompileLibraries.Add(item.Name); } } } List <CompilationLibrary> dependencyCompilationLibrary = DependencyContext.Load(assembly) .CompileLibraries.Where(de => PluginInfos.All(m => m.Name != de.Name) && de.Name != currentName && !CompileLibraries.Contains(de.Name)) .ToList(); if (LoadedAssemblies == null) { LoadedAssemblies = AppDomain.CurrentDomain.GetAssemblies().ToDictionary(m => m.GetName().Name); } dependencyCompilationLibrary.Each(libaray => { foreach (var item in libaray.ResolveReferencePaths(new DependencyAssemblyResolver(Path.GetDirectoryName(assembly.Location)))) { string assemblyName = AssemblyName.GetAssemblyName(item).Name; if (!LoadedAssemblies.ContainsKey(assemblyName)) { Assembly assemblyDep = AssemblyLoadContext.Default.LoadFromAssemblyPath(item); DependencyAssemblies.Add(assemblyDep); LoadedAssemblies.Add(assemblyName, assemblyDep); } } }); PluginDescriptor plugin = null; foreach (var typeInfo in assembly.DefinedTypes) { if (typeInfo.IsAbstract || typeInfo.IsInterface) { continue; } if (PluginTypeInfo.IsAssignableFrom(typeInfo)) { plugin = new PluginDescriptor { PluginType = typeInfo.AsType(), Assembly = assembly, Dependency = dependencyCompilationLibrary, CurrentPluginPath = CurrentPath }; } } if (plugin != null) { PluginActivtor.LoadedPlugins.Add(plugin); } }
/// <summary> /// Applies patchers to all assemblies in the given directory and loads patched assemblies into memory. /// </summary> /// <param name="directory">Directory to load CLR assemblies from.</param> public void PatchAndLoad() { // First, create a copy of the assembly dictionary as the initializer can change them var assemblies = new Dictionary <string, AssemblyDefinition>(AssembliesToPatch, StringComparer.InvariantCultureIgnoreCase); // Next, initialize all the patchers foreach (var assemblyPatcher in PatcherPluginsSafe) { try { assemblyPatcher.Initializer?.Invoke(); } catch (Exception ex) { Logger.LogError($"Failed to run initializer of {assemblyPatcher.TypeName}: {ex}"); } } // Then, perform the actual patching var patchedAssemblies = new HashSet <string>(StringComparer.InvariantCultureIgnoreCase); var resolvedAssemblies = new Dictionary <string, string>(); // TODO: Maybe instead reload the assembly and repatch with other valid patchers? var invalidAssemblies = new HashSet <string>(StringComparer.InvariantCultureIgnoreCase); foreach (var assemblyPatcher in PatcherPluginsSafe) { foreach (string targetDll in assemblyPatcher.TargetDLLs()) { if (AssembliesToPatch.TryGetValue(targetDll, out var assembly) && !invalidAssemblies.Contains(targetDll)) { Logger.LogInfo($"Patching [{assembly.Name.Name}] with [{assemblyPatcher.TypeName}]"); try { assemblyPatcher.Patcher?.Invoke(ref assembly); } catch (Exception e) { Logger.LogError($"Failed to run [{assemblyPatcher.TypeName}] when patching [{assembly.Name.Name}]. This assembly will not be patched. Error: {e}"); patchedAssemblies.Remove(targetDll); invalidAssemblies.Add(targetDll); continue; } AssembliesToPatch[targetDll] = assembly; patchedAssemblies.Add(targetDll); foreach (var resolvedAss in AppDomain.CurrentDomain.GetAssemblies()) { var name = Utility.TryParseAssemblyName(resolvedAss.FullName, out var assName) ? assName.Name : resolvedAss.FullName; // Report only the first type that caused the assembly to load, because any subsequent ones can be false positives if (!resolvedAssemblies.ContainsKey(name)) { resolvedAssemblies[name] = assemblyPatcher.TypeName; } } } } } // Check if any patched assemblies have been already resolved by the CLR // If there are any, they cannot be loaded by the preloader var patchedAssemblyNames = new HashSet <string>(assemblies.Where(kv => patchedAssemblies.Contains(kv.Key)).Select(kv => kv.Value.Name.Name), StringComparer.InvariantCultureIgnoreCase); var earlyLoadAssemblies = resolvedAssemblies.Where(kv => patchedAssemblyNames.Contains(kv.Key)).ToList(); if (earlyLoadAssemblies.Count != 0) { Logger.LogWarning(new StringBuilder() .AppendLine("The following assemblies have been loaded too early and will not be patched by preloader:") .AppendLine(string.Join(Environment.NewLine, earlyLoadAssemblies.Select(kv => $"* [{kv.Key}] (first loaded by [{kv.Value}])").ToArray())) .AppendLine("Expect unexpected behavior and issues with plugins and patchers not being loaded.") .ToString()); } // Finally, load patched assemblies into memory if (ConfigDumpAssemblies.Value || ConfigLoadDumpedAssemblies.Value) { if (!Directory.Exists(DumpedAssembliesPath)) { Directory.CreateDirectory(DumpedAssembliesPath); } foreach (KeyValuePair <string, AssemblyDefinition> kv in assemblies) { string filename = kv.Key; var assembly = kv.Value; if (patchedAssemblies.Contains(filename)) { assembly.Write(Path.Combine(DumpedAssembliesPath, filename)); } } } if (ConfigBreakBeforeLoadAssemblies.Value) { Logger.LogInfo($"BepInEx is about load the following assemblies:\n{String.Join("\n", patchedAssemblies.ToArray())}"); Logger.LogInfo($"The assemblies were dumped into {DumpedAssembliesPath}"); Logger.LogInfo("Load any assemblies into the debugger, set breakpoints and continue execution."); Debugger.Break(); } foreach (var kv in assemblies) { string filename = kv.Key; var assembly = kv.Value; // Note that since we only *load* assemblies, they shouldn't trigger dependency loading // Not loading all assemblies is very important not only because of memory reasons, // but because some games *rely* on that because of messed up internal dependencies. if (patchedAssemblies.Contains(filename)) { Assembly loadedAssembly; if (ConfigLoadDumpedAssemblies.Value) { loadedAssembly = Assembly.LoadFile(Path.Combine(DumpedAssembliesPath, filename)); } else { using (var assemblyStream = new MemoryStream()) { assembly.Write(assemblyStream); loadedAssembly = Assembly.Load(assemblyStream.ToArray()); } } LoadedAssemblies.Add(filename, loadedAssembly); Logger.LogDebug($"Loaded '{assembly.FullName}' into memory"); } // Though we have to dispose of all assemblies regardless of them being patched or not assembly.Dispose(); } // Finally, run all finalizers foreach (var assemblyPatcher in PatcherPluginsSafe) { try { assemblyPatcher.Finalizer?.Invoke(); } catch (Exception ex) { Logger.LogError($"Failed to run finalizer of {assemblyPatcher.TypeName}: {ex}"); } } }
/// <summary> /// Scans the specified paths for plugins & loads them into the AppDomain /// </summary> /// <param name="paths"></param> /// <exception cref="DirectoryNotFoundException"></exception> public void DiscoverPlugins(params string[] paths) { int pluginInstances = 0; paths = paths.Where(x => { if (Directory.Exists(x)) { return(true); } else { Log.Warn($"Could not load plugins from folder \"{x}\", folder does not exist!"); return(false); } }).ToArray(); foreach (var path in paths) { if (!Directory.Exists(path)) { throw new DirectoryNotFoundException("Directory not found: " + path); } } Dictionary <Assembly, string> loadedAssemblies = new Dictionary <Assembly, string>(); //List<(Assembly assembly, string path)> loadedAssemblies = new List<(Assembly assembly, string path)>(); int processed = 0; foreach (var rawPath in paths) { string path = rawPath; string[] files = Directory.GetFiles(path, "*.dll", SearchOption.AllDirectories); foreach (string file in files) { try { string filename = Path.GetFileNameWithoutExtension(file); if (!Config.GetProperty($"plugin.{filename}.enabled", true)) { Log.Info($"Not loading \"{Path.GetRelativePath(rawPath, file)}\" as it was disabled by config."); continue; } path = Path.GetDirectoryName(file); Assembly[] result; ProcessFile(path, file, out result); processed++; if (result == null) { continue; } foreach (var assembly in result) { if (!loadedAssemblies.ContainsKey(assembly)) { loadedAssemblies.Add(assembly, path); } } } catch (BadImageFormatException ex) { if (Log.IsDebugEnabled) { Log.Debug($"File is not a .NET Assembly ({file})", ex); } } catch (Exception ex) { Log.Error($"Failed loading \"{file}\"", ex); } } } Log.Info($"Loaded {loadedAssemblies.Count} assemblies from {processed} processed files."); //List<OpenPlugin> plugins = new List<OpenPlugin>(); LinkedList <PluginConstructorData> constructorDatas = new LinkedList <PluginConstructorData>(); foreach (var assembly in loadedAssemblies) { if (assembly.Key != null) { var constructors = FindPluginConstructors(assembly.Key); foreach (var constructor in constructors) { var existing = constructorDatas.FirstOrDefault(x => x.Type == constructor.Type); if (existing != null) { if (!existing.ReferencesOtherPlugin && constructor.ReferencesOtherPlugin) { var found = constructorDatas.Find(existing); if (found != null) { found.Value = constructor; continue; } } } constructorDatas.AddLast(constructor); } } } Dictionary <Assembly, List <OpenPlugin> > assemblies = new Dictionary <Assembly, List <OpenPlugin> >(); //Load all plugins that do NOT have a reference to any other plugins. foreach (var grouped in constructorDatas.Where(x => !x.ReferencesOtherPlugin).GroupBy(x => x.Type.Assembly)) { List <OpenPlugin> assemblyInstances = new List <OpenPlugin>(); foreach (var constructor in grouped) { if (CreateInstance(constructor, out OpenPlugin instance, assemblies)) { Services.RegisterSingleton(instance.GetType(), instance); pluginInstances++; assemblyInstances.Add(instance); } } if (!assemblies.ContainsKey(grouped.Key)) { assemblies.Add(grouped.Key, assemblyInstances); } else { assemblies[grouped.Key].AddRange(assemblyInstances); } } LinkedList <PluginConstructorData> ordered = new LinkedList <PluginConstructorData>(); var requiresOthers = constructorDatas.Where(x => x.ReferencesOtherPlugin).ToArray(); foreach (var grouped in requiresOthers) { var thisNode = ordered.Find(grouped); if (thisNode == null) { thisNode = ordered.AddLast(grouped); } var otherPlugins = grouped.Dependencies.Where(x => x.IsPluginInstance).Select(x => x.Type).ToArray(); foreach (var otherDependency in otherPlugins) { var found = requiresOthers.FirstOrDefault(x => x.Type == otherDependency); if (found != null) { ordered.AddBefore(thisNode, found); } } } bool done = false; var current = ordered.First; do { var currentValue = current?.Value; var next = current?.Next; if (next == null || currentValue == null) { done = true; break; } if (currentValue.Requires(next.Value)) { current.Value = next.Value; next.Value = currentValue; } current = next; } while (!done); foreach (var item in ordered) { // List<OpenPlugin> assemblyInstances = new List<OpenPlugin>(); if (Services.TryResolve(item.Type, out _)) { continue; } if (CreateInstance(item, out var instance, assemblies)) { Services.RegisterSingleton(item.Type, instance); //.Add(instance); pluginInstances++; if (!assemblies.ContainsKey(item.Type.Assembly)) { assemblies.Add(item.Type.Assembly, new List <OpenPlugin>() { instance }); } else { assemblies[item.Type.Assembly].Add(instance); } } } Log.Info($"Registered {pluginInstances} plugin instances"); foreach (var grouped in assemblies) { LoadedAssemblies.Add(grouped.Key, new LoadedAssembly(grouped.Key, grouped.Value.Select(x => x.GetType()), new Assembly[0], grouped.Key.Location)); } }
public ArchiveContext(string path, ZipArchive archive, Assembly assembly) { Path = path; Archive = archive; LoadedAssemblies.Add(assembly); }
public static void RegisterAssembly(string assemblyPath) { var assembly = Assembly.LoadFrom(assemblyPath); LoadedAssemblies.Add(assembly); }
/// <summary> /// This is called when a new assembly is loaded, we need to know this /// </summary> /// <param name="sender">object</param> /// <param name="args">AssemblyLoadEventArgs</param> private void AssemblyLoad(object sender, AssemblyLoadEventArgs args) { var loadedAssembly = args.LoadedAssembly; var assemblyName = loadedAssembly.GetName().Name; if (Log.IsVerboseEnabled()) { Log.Verbose().WriteLine("Loaded {0}", assemblyName); } LoadedAssemblies[assemblyName] = loadedAssembly; if (!_applicationConfig.ScanForEmbeddedAssemblies) { return; } // Ignore resource checking on certain assemblies if (AssembliesToIgnore.IsMatch(assemblyName)) { return; } string[] resources; try { resources = Resources.GetCachedManifestResourceNames(loadedAssembly); } catch (Exception ex) { Log.Warn().WriteLine(ex, "Couldn't retrieve resources from {0}", loadedAssembly.GetName().Name); return; } foreach (var resource in resources) { var resourceMatch = _assemblyResourceNameRegex.Match(resource); if (!resourceMatch.Success) { continue; } var embeddedAssemblyName = resourceMatch.Groups["assembly"].Value; if (LoadedAssemblies.ContainsKey(embeddedAssemblyName)) { // Ignoring already loaded assembly, as we cannot unload. continue; } var newAssemblyLocation = new AssemblyLocationInformation(embeddedAssemblyName, loadedAssembly, resource); if (AvailableAssemblies.TryGetValue(embeddedAssemblyName, out var availableAssemblyLocationInformation)) { if (availableAssemblyLocationInformation.FileDate > newAssemblyLocation.FileDate) { continue; } } if (Log.IsVerboseEnabled()) { Log.Verbose().WriteLine("Detected additional assembly {0} in {1}", embeddedAssemblyName, loadedAssembly.GetName().Name); } AvailableAssemblies[embeddedAssemblyName] = newAssemblyLocation; } }
public IEnumerable <Type> GetTypes <T>() { return(LoadedAssemblies.SelectMany(ass => ass.Types) .Where(t => typeof(T).IsAssignableFrom(t)).ToList()); }
/// <summary> /// Do the one time scan of all the assemblies /// </summary> private void ScanForAssemblies() { var assemblies = new HashSet <AssemblyLocationInformation>(); if (_applicationConfig.ScanForEmbeddedAssemblies) { foreach (var loadedAssembly in LoadedAssemblies.Where(pair => !AssembliesToIgnore.IsMatch(pair.Key)).Select(pair => pair.Value).ToList()) { string[] resources; try { resources = Resources.GetCachedManifestResourceNames(loadedAssembly); } catch (Exception ex) { Log.Warn().WriteLine(ex, "Couldn't retrieve resources from {0}", loadedAssembly.GetName().Name); continue; } foreach (var resource in resources) { var resourceMatch = _assemblyResourceNameRegex.Match(resource); if (resourceMatch.Success) { assemblies.Add(new AssemblyLocationInformation(resourceMatch.Groups["assembly"].Value, loadedAssembly, resource)); } } } } if (_applicationConfig.UseStrictChecking) { foreach (var applicationConfigScanDirectory in _applicationConfig.ScanDirectories) { if (!Directory.Exists(applicationConfigScanDirectory)) { throw new DirectoryNotFoundException(applicationConfigScanDirectory); } } } foreach (var fileLocation in FileLocations.Scan(_applicationConfig.ScanDirectories, _assemblyFilenameRegex, SearchOption.TopDirectoryOnly)) { assemblies.Add(new AssemblyLocationInformation(fileLocation.Item2.Groups["assembly"].Value, fileLocation.Item1)); } // Reduce step 1) Take from the double assemblies only those which are embedded & on the file system in the probing path foreach (var assemblyGroup in assemblies.GroupBy(information => information.Name).ToList()) { var groupList = assemblyGroup.ToList(); if (groupList.Count <= 1) { continue; } // Remove filesystem assemblies from the list which are not in the AssemblyResolveDirectories var unneededAssemblies = groupList.Where(info => !info.IsEmbedded && !info.IsOnProbingPath).ToList(); if (groupList.Count - unneededAssemblies.Count < 1) { continue; } foreach (var unneededAssemblyInformation in unneededAssemblies) { assemblies.Remove(unneededAssemblyInformation); } } // Reduce step 2) foreach (var assemblyGroup in assemblies.GroupBy(information => information.Name).ToList()) { var groupList = assemblyGroup.ToList(); if (groupList.Count <= 1) { continue; } // Remove assemblies which are older foreach (var unneededAssemblyInformation in groupList.OrderBy(info => info.FileDate).Skip(1).ToList()) { assemblies.Remove(unneededAssemblyInformation); } } // Create the assembly locations foreach (var assemblyLocationInformation in assemblies) { AvailableAssemblies[assemblyLocationInformation.Name] = assemblyLocationInformation; } }
/// <summary> /// Load an assembly via a file, this used via Assembly.Load or Assembly.LoadFrom depending on where the file is or can be stored /// </summary> /// <param name="additionalInformation">AssemblyLocationInformation used for some decisions</param> /// <returns>Assembly</returns> private Assembly LoadFromFile(AssemblyLocationInformation additionalInformation) { // Get the assembly name from the file var assemblyName = AssemblyName.GetAssemblyName(additionalInformation.Filename); // Check the cache again, this time with the "real" name if (LoadedAssemblies.TryGetValue(assemblyName.Name, out var assembly)) { if (Log.IsInfoEnabled()) { Log.Info().WriteLine("Returned {0} from cache.", assemblyName.Name); } return(assembly); } var destination = $@"{FileLocations.AddonsLocation}\{assemblyName.Name}.dll"; var destinationIsNotSource = !destination.Equals(additionalInformation.Filename, StringComparison.OrdinalIgnoreCase); if (Log.IsDebugEnabled() && !destinationIsNotSource) { Log.Debug().WriteLine("Skipping copy, as destination and source would be the same."); } if (_applicationConfig.CopyAssembliesToProbingPath && FileLocations.AddonsLocation != null && destinationIsNotSource) { try { if (ShouldWrite(additionalInformation, destination)) { if (Log.IsVerboseEnabled()) { Log.Verbose().WriteLine("Creating a copy of {0} to {1}, solving potential context loading issues.", additionalInformation.Filename, destination); } File.Copy(additionalInformation.Filename, destination); // Register delete on exit, this is done by calling a command _assembliesToDeleteAtExit.Add(destination); } // Load via the assembly name, it's not inside the probing path assembly = Assembly.Load(assemblyName); if (assembly != null) { return(assembly); } } catch (Exception ex) { Log.Warn().WriteLine(ex, "Couldn't create a copy of {0} to {1}.", additionalInformation.Filename, destination); } } if (Log.IsVerboseEnabled()) { Log.Verbose().WriteLine("Loading {0} from {1}.", additionalInformation.Name, additionalInformation.Filename); } try { return(Assembly.LoadFrom(additionalInformation.Filename)); } catch (Exception ex) { Log.Error().WriteLine(ex, "Couldn't load assembly from file {0}", additionalInformation.Filename); } return(null); }
internal void InitialiseDependencyResolvers() { _dependencyResolvers = LoadedAssemblies.Select(x => new DependencyResolver(x.Value)).ToList(); }
public void LoadPlugins() { int pluginInstances = 0; Dictionary <Assembly, List <Plugin> > assemblies = new Dictionary <Assembly, List <Plugin> >(); //Load all plugins that do NOT have a reference to any other plugins. foreach (var grouped in PluginConstructors.Where(x => !x.ReferencesOtherPlugin).GroupBy(x => x.Type.Assembly).ToArray()) { List <Plugin> assemblyInstances = new List <Plugin>(); foreach (var constructor in grouped) { if (CreateInstance(constructor, out Plugin instance, assemblies)) { PluginContainer.RegisterSingleton(instance.GetType(), instance); pluginInstances++; assemblyInstances.Add(instance); } PluginConstructors.Remove(constructor); } if (!assemblies.ContainsKey(grouped.Key)) { assemblies.Add(grouped.Key, assemblyInstances); } else { assemblies[grouped.Key].AddRange(assemblyInstances); } } LinkedList <PluginConstructorData> ordered = new LinkedList <PluginConstructorData>(); var requiresOthers = PluginConstructors.Where(x => x.ReferencesOtherPlugin).ToArray(); foreach (var grouped in requiresOthers) { var thisNode = ordered.Find(grouped); if (thisNode == null) { thisNode = ordered.AddLast(grouped); } var otherPlugins = grouped.Dependencies.Where(x => x.IsPluginInstance).Select(x => x.Type).ToArray(); foreach (var otherDependency in otherPlugins) { var found = requiresOthers.FirstOrDefault(x => x.Type == otherDependency); if (found != null) { ordered.AddBefore(thisNode, found); } } } bool done = false; var current = ordered.First; do { var currentValue = current?.Value; var next = current?.Next; if (next == null || currentValue == null) { done = true; break; } if (currentValue.Requires(next.Value)) { current.Value = next.Value; next.Value = currentValue; } current = next; } while (!done); foreach (var item in ordered) { // List<OpenPlugin> assemblyInstances = new List<OpenPlugin>(); if (PluginContainer.TryResolve(item.Type, out _)) { continue; } if (CreateInstance(item, out var instance, assemblies)) { PluginContainer.RegisterSingleton(item.Type, instance); //.Add(instance); pluginInstances++; if (!assemblies.ContainsKey(item.Type.Assembly)) { assemblies.Add(item.Type.Assembly, new List <Plugin>() { instance }); } else { assemblies[item.Type.Assembly].Add(instance); } } } Log.Info($"Registered {pluginInstances} plugin instances"); foreach (var grouped in assemblies) { if (LoadedAssemblies.ContainsKey(grouped.Key)) { LoadedAssemblies[grouped.Key].PluginTypes.AddRange(grouped.Value.Select(x => x.GetType())); continue; } else { LoadedAssemblies.Add(grouped.Key, new LoadedAssembly(grouped.Key, grouped.Value.Select(x => x.GetType()), new Assembly[0], grouped.Key.Location)); } } }
private Type GetExceptionType(RpcErrorTypeBehavior typeResolution) { Type tException = typeof(ApplicationException); Assembly found = tException.Assembly; if (typeResolution == RpcErrorTypeBehavior.NoTypeResolution) { return(tException); } if (!HasFullTypeName || !HasAssemblyName || String.IsNullOrEmpty(FullTypeName) || String.IsNullOrEmpty(AssemblyName)) { return(tException); } if (!ValidTypeName.IsMatch(FullTypeName)) { return(tException); } if (typeResolution == RpcErrorTypeBehavior.OnlyUseMsCorLibTypes) { return(found.GetType(FullTypeName) ?? tException); } AssemblyName name = new AssemblyName(AssemblyName); if (name.CodeBase != null) { return(tException); } if (null != (found = LoadedAssemblies.Lookup(name))) { return(found.GetType(FullTypeName) ?? tException); } if (typeResolution == RpcErrorTypeBehavior.OnlyUseLoadedAssemblies) { return(tException); } if (typeResolution == RpcErrorTypeBehavior.OnlyLoadStrongNamed && name.GetPublicKeyToken() == null) { return(tException); } Type test = Type.GetType(String.Format("{0}, {1}", FullTypeName, name)); if (test != null) { return(test); } if (typeResolution == RpcErrorTypeBehavior.LoadAnyAssembly) { return(Type.GetType(String.Format("{0}, {1}", FullTypeName, new AssemblyName(name.Name))) ?? tException); } return(tException); }
internal static void Run() { JEMLogger.Log("Loading appcfg.", "APP"); AppConfig.LoadConfiguration(); if (!Directory.Exists(AssembliesDirectory)) { JEMLogger.LogError($"Assemblies directory `{AssembliesDirectory}` does not exist.", "APP"); return; } var assembliesTargets = AssembliesDirectory + JEMVar.DirectorySeparatorChar + AppConfig.Loaded.AssembliesTargetsFile; if (!File.Exists(assembliesTargets)) { JEMLogger.LogError($"File defining target assemblies `{assembliesTargets}` does not exist.", "APP"); return; } AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => { JEMLogger.LogError("Failed to resolve assembly " + args.Name, "APP"); return(Assembly.LoadFrom(args.Name)); }; AssembliesNames = File.ReadAllLines(assembliesTargets); JEMLogger.Log($"{AssembliesNames.Length} target assemblies found.", "APP"); foreach (var a in AssembliesNames) { JEMLogger.Log($"\t{a}", "APP"); } Console.WriteLine(); if (Directory.Exists(DeployDirectory)) { Directory.Delete(DeployDirectory, true); } Directory.CreateDirectory(DeployDirectory); foreach (var a in AssembliesNames) { var file = AssembliesDirectory + JEMVar.DirectorySeparatorChar + a + ".dll"; AssemblyName assemblyName = null; try { assemblyName = AssemblyName.GetAssemblyName(file); } catch (Exception e) { JEMLogger.LogException(e, "APP"); } var assembly = assemblyName == null ? null : Assembly.Load(assemblyName); if (assembly == null) { JEMLogger.LogError($"Unable to load assembly `{file}`", "APP"); } else { JEMLogger.Log($"Assembly {file} loaded..", "APP"); LoadedAssemblies.Add(assembly); } } JEMLogger.Log("Generating.", "APP"); foreach (var assembly in LoadedAssemblies) { try { GenerateOffAssembly(assembly); } catch (TypeLoadException e) { Console.WriteLine(e); throw; } } }
/*public delegate void AssemblyLoadedHandler(AssemblyLoadedEventArgs args); * * public class AssemblyLoadedEventArgs * { * public Assembly Assembly { get; private set; } * * public AssemblyLoadedEventArgs(Assembly assembly) * { * Assembly = assembly; * } * } * * public event AssemblyLoadedHandler AssemblyLoaded; * * private void OnAssemblyLoaded(Assembly assem) * { * if (AssemblyLoaded != null) * { * AssemblyLoaded(new AssemblyLoadedEventArgs(assem)); * } * } */ /// <summary> /// Load all types which inherit from NodeModel whose assemblies are located in /// the bin/nodes directory. Add the types to the searchviewmodel and /// the controller's dictionaries. /// </summary> public virtual List <Type> LoadNodeModels(string folderToSearch, bool searchAppDomain) { var loadedAssembliesByPath = new Dictionary <string, Assembly>(); var loadedAssembliesByName = new Dictionary <string, Assembly>(); var allNodeAssemblies = new List <System.Reflection.Assembly>(); // cache the loaded assembly information if (searchAppDomain) { foreach ( var assembly in AppDomain.CurrentDomain.GetAssemblies()) { try { loadedAssembliesByPath[assembly.Location] = assembly; loadedAssembliesByName[assembly.FullName] = assembly; } catch { } } allNodeAssemblies = AppDomain.CurrentDomain.GetAssemblies().ToList(); } var loadedTypes = new List <Type>(); // going to look in all currently loaded assemblies for nodes, then we'll also look // in a specific folder of the resources or data folder, unsure on this path yet... string path = Application.dataPath; Debug.Log(path); path = Path.Combine(path, folderToSearch); Debug.Log(path); List <Assembly> allAssembliesinbuild = new List <Assembly>(); foreach (string dll in Directory.GetFiles(path, "*.dll")) { allAssembliesinbuild.Add(Assembly.LoadFile(dll)); } allNodeAssemblies.AddRange(allAssembliesinbuild); //iterate each assembly location foreach (var assemblyPath in allNodeAssemblies.Select(x => x.Location).ToList()) { Debug.Log("current assembly path is " + assemblyPath); //get the filename at each location and check it's not null var fn = Path.GetFileName(assemblyPath); if (fn == null) { continue; } Debug.Log("filename is " + fn); // if the assembly has already been loaded, then // skip it, otherwise cache it. if (LoadedAssemblyNames.Contains(fn)) { continue; } LoadedAssemblyNames.Add(fn); try { Assembly assembly; if (!loadedAssembliesByPath.TryGetValue(assemblyPath, out assembly)) { Debug.Log("about to load assembly from" + assemblyPath); assembly = Assembly.LoadFrom(assemblyPath); loadedAssembliesByName[assembly.GetName().Name] = assembly; loadedAssembliesByPath[assemblyPath] = assembly; } loadedTypes.AddRange(LoadNodesFromAssembly(assembly)); LoadedAssemblies.Add(assembly); //TODO possibly readd event that fires when assemlbly loaded //OnAssemblyLoaded(assembly); } catch (BadImageFormatException) { //swallow these warnings. } catch (Exception e) { Debug.LogException(e); } } //AppDomain.CurrentDomain.AssemblyResolve -= resolver; return(loadedTypes); }