private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) { // Handle the RhinoCommon case. if (args.Name.StartsWith("RhinoCommon", StringComparison.OrdinalIgnoreCase) && !args.Name.StartsWith("RhinoCommon.resources", StringComparison.OrdinalIgnoreCase)) { return(Assembly.GetExecutingAssembly()); } // Get the significant name of the assembly we're looking for. string searchname = args.Name; // Do not attempt to handle resource searching. int index = searchname.IndexOf(".resources", StringComparison.Ordinal); if (index > 0) { return(null); } // The resolver is commonly called multiple times with the same search name. // Keep the results around so we don't keep doing the same job over and over if (m_match_dictionary != null && m_match_dictionary.ContainsKey(args.Name)) { return(m_match_dictionary[args.Name]); } bool probably_python = false; index = searchname.IndexOf(','); if (index > 0) { searchname = searchname.Substring(0, index); } else { // Python scripts typically just look for very short names, like "MyFunctions.dll" if (searchname.EndsWith(".dll", StringComparison.OrdinalIgnoreCase)) { searchname = searchname.Substring(0, searchname.Length - ".dll".Length); } probably_python = true; } // See if the assembly is already loaded. var loaded_assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (var loaded_assembly in loaded_assemblies) { if (loaded_assembly.FullName.StartsWith(searchname + ",", StringComparison.OrdinalIgnoreCase)) { return(loaded_assembly); } } List <string> potential_files = new List <string>(); // Collect all potential files in the plug-in directories. #if RHINO_SDK string[] plugin_folders = HostUtils.GetAssemblySearchPaths(); if (plugin_folders != null) { foreach (string plugin_folder in plugin_folders) { string[] files = Directory.GetFiles(plugin_folder, @"*.dll", SearchOption.TopDirectoryOnly); //Why TopDirectoryOnly? if (files != null) { potential_files.AddRange(files); } files = Directory.GetFiles(plugin_folder, @"*.rhp", SearchOption.TopDirectoryOnly); //Why TopDirectoryOnly? if (files != null) { potential_files.AddRange(files); } } } #endif if (probably_python) { string current_dir = Directory.GetCurrentDirectory(); if (!string.IsNullOrEmpty(current_dir)) { string[] files = Directory.GetFiles(current_dir, @"*.dll", SearchOption.TopDirectoryOnly); //Why TopDirectoryOnly? if (files != null) { potential_files.AddRange(files); } } } // Collect all potential files in the custom directories. if (m_custom_folders != null) { foreach (string custom_folder in m_custom_folders) { string[] files = Directory.GetFiles(custom_folder, @"*.dll", SearchOption.TopDirectoryOnly); //Why TopDirectoryOnly? if (files != null) { potential_files.AddRange(files); } files = Directory.GetFiles(custom_folder, @"*.rhp", SearchOption.TopDirectoryOnly); //Why TopDirectoryOnly? if (files != null) { potential_files.AddRange(files); } } } // Collect all potential files in the custom file list. if (m_custom_files != null) { potential_files.AddRange(m_custom_files); } // Remove the already loaded assemblies from the "potential" list. We've // already tested these. for (int i = 0; i < loaded_assemblies.Length; i++) { if (loaded_assemblies[i].GlobalAssemblyCache) { continue; } if (loaded_assemblies[i].IsDynamic) { continue; //dynamic assemblies won't have a Location anyways. } try { // 6 Feb 2017 S. Baer (RH-35794) // Remove loaded assemblies using filename as comparison. On systems // where the same assembly is located in multiple search path locations // we will start throwing exceptions when attempting to load those // assemblies (even if they are not the ones we are looking for). string filename = Path.GetFileName(loaded_assemblies[i].Location); for (int j = potential_files.Count - 1; j >= 0; j--) { string potential_filename = Path.GetFileName(potential_files[j]); if (string.Compare(filename, potential_filename, StringComparison.OrdinalIgnoreCase) == 0) { potential_files.RemoveAt(j); } } } catch { } } #if RHINO_SDK // 7 Feb 2017 S. Baer (RH-30818) // Remove native DLLs from the list of potentials for (int i = potential_files.Count - 1; i >= 0; i--) { if (!HostUtils.IsManagedDll(potential_files[i])) { potential_files.RemoveAt(i); } } #endif // Sort all potential files based on fuzzy name matches. FuzzyComparer fuzzy = new FuzzyComparer(searchname); potential_files.Sort(fuzzy); // 23 August 2012 S. Baer // Make sure that at least part of the searchname matches part of the filename // Just use the first 5 characters as a required pattern in the filename const int length_match = 5; string must_be_in_filename = searchname.Substring(0, searchname.Length > length_match ? length_match : searchname.Length); Assembly asm = null; foreach (string file in potential_files) { if (file.IndexOf(must_be_in_filename, StringComparison.InvariantCultureIgnoreCase) == -1) { continue; } asm = TryLoadAssembly(file, searchname); if (asm != null) { break; } } if (m_match_dictionary == null) { m_match_dictionary = new Dictionary <string, Assembly>(); } if (!m_match_dictionary.ContainsKey(args.Name)) { m_match_dictionary.Add(args.Name, asm); } return(asm); }