static Type GetRhinoDotNetType(string name) { System.Reflection.Assembly rhino_dot_net = HostUtils.GetRhinoDotNetAssembly(); if (null == rhino_dot_net) { return(null); } return(rhino_dot_net.GetType(name)); }
/// <summary> /// For derived class implementers. /// <para>This method is called with argument true when class user calls Dispose(), while with argument false when /// the Garbage Collector invokes the finalizer, or Finalize() method.</para> /// <para>You must reclaim all used unmanaged resources in both cases, and can use this chance to call Dispose on disposable fields if the argument is true.</para> /// <para>Also, you must call the base virtual method within your overriding method.</para> /// </summary> /// <param name="disposing">true if the call comes from the Dispose() method; false if it comes from the Garbage Collector finalizer.</param> protected virtual void Dispose(bool disposing) { if (IntPtr.Zero == m_ptr || m__parent is ConstCastHolder) { return; } Geometry.MeshHolder mh = m__parent as Geometry.MeshHolder; if (mh != null) { mh.ReleaseMesh(); } if (m_bDestructOnDispose) { bool in_finalizer = !disposing; if (in_finalizer) { // 11 Feb 2013 (S. Baer) RH-16157 // When running in the finalizer, the destructor is being called on the GC // thread which results in nearly impossible to track down exceptions. // Mask the exception in this case and post information to our logging system // about the exception so we can better analyze and try to figure out what // is going on try { UnsafeNativeMethods.ON_Object_Delete(m_ptr); } catch (Exception ex) { HostUtils.ExceptionReport(ex); } } else { // See above. In this case we are running on the main thread of execution // and throwing an exception is a good thing so we can analyze and quickly // fix whatever is going wrong UnsafeNativeMethods.ON_Object_Delete(m_ptr); } if (m_unmanaged_memory > 0) { GC.RemoveMemoryPressure(m_unmanaged_memory); } } m_ptr = IntPtr.Zero; m_disposed = true; }
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); }
public int Compare(string x, string y) { bool xExists = File.Exists(x); bool yExists = File.Exists(y); if (!xExists && !yExists) { return(0); } if (!xExists) { return(+1); } if (!yExists) { return(-1); } // This can be made a lot smarter with substring searches. string xFileName = Path.GetFileName(x); string yFileName = Path.GetFileName(y); int xIndex = xFileName == null ? -1 : xFileName.IndexOf(m_search, StringComparison.OrdinalIgnoreCase); int yIndex = yFileName == null ? -1 : yFileName.IndexOf(m_search, StringComparison.OrdinalIgnoreCase); // 4 April 2012 - S. Baer // If the file names are the same, the highest version number or most // recent file date is sorted to the top. Plug-ins like PanelingTools // have historically moved around on where they are installed on a user's // computer, so we may end up with duplicates if (xIndex >= 0 && yIndex >= 0 && string.Compare(xFileName, yFileName, StringComparison.OrdinalIgnoreCase) == 0) { try { // 25 August 2015 - David Rutten: // Error reports: // http://mcneel.myjetbrains.com/youtrack/issue/RH-30818 // https://app.raygun.io/dashboard/6bsfxg/errors/561473847 // seem to originate on one of the ReflectionOnlyLoadFrom calls below, // but they're already in a try_catch block. I'm really not sure how to // determine whether an assembly will load prior to loading it. // 3 Oct 2017 - S. Baer (RH-35794) // Reflection loading two assemblies into the same appdomain is asking for exceptions // Luckily, there is another way... Use AssemblyName.GetAssemblyName var xAssemblyName = AssemblyName.GetAssemblyName(x); var yAssemblyName = AssemblyName.GetAssemblyName(y); Version xVersion = xAssemblyName.Version; Version yVersion = yAssemblyName.Version; int rc = xVersion.CompareTo(yVersion); if (rc != 0) { return(rc); } // Same version. Try using the file date FileInfo xInfo = new FileInfo(x); FileInfo yInfo = new FileInfo(y); rc = xInfo.LastAccessTimeUtc.CompareTo(yInfo.LastAccessTimeUtc); if (rc != 0) { return(rc); } } catch (Exception ex) { HostUtils.ExceptionReport("duplicate assembly resolve", ex); } } if (xIndex < 0) { xIndex = int.MaxValue; } if (yIndex < 0) { yIndex = int.MaxValue; } return(xIndex.CompareTo(yIndex)); }
public static int LoadPlugIn(string path) { HostUtils.SendDebugToCommandLine = true; HostUtils.DebugString("[MonoHost::LoadPlugIn] Start"); if (!m_bUsingMono) { m_bUsingMono = true; // Don't turn visual styles on yet, they seem pretty flakey as of // Mono 2.4.2 //System.Windows.Forms.Application.EnableVisualStyles(); InitializeExceptionHandling(); HostUtils.InitializeRhinoCommon(); HostUtils.DebugString("Attempt to initialize MonoMac"); Type t = typeof(System.Windows.Forms.Application); if (t != null) { System.Reflection.MethodInfo mi = t.GetMethod("MonoMacInit", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static); if (mi != null) { HostUtils.DebugString("Got methodinfo for MonoMacInit"); mi.Invoke(null, null); } } } // 7 Apr 2013, S. Baer // Mac plug-ins can now be located inside of OSX plug-in bundles. // The native plug-in manager may just pass us the bundle path // See if the path refers to a bundle. If that is the case, // look inside the bundle to find the actual assembly var temp_path = System.IO.Path.Combine(path, "Contents"); temp_path = System.IO.Path.Combine(temp_path, "Mono"); if (System.IO.Directory.Exists(temp_path)) { var files = System.IO.Directory.GetFiles(temp_path, "*.rhp"); if (files != null && files.Length > 0) { path = files[0]; } } HostUtils.DebugString("path = " + path); // Reflection Load assembly first in order to check versioning // and make sure the plug-in hasn't already been loaded System.Reflection.Assembly plugin_assembly; try { plugin_assembly = System.Reflection.Assembly.ReflectionOnlyLoadFrom(path); } catch (Exception) { plugin_assembly = null; } HostUtils.DebugString("ReflectionOnlyLoadFrom succeeded"); if (null == plugin_assembly) { return((int)MonoLoadResult.error_not_dotnet); } //make sure this assembly has not alread been loaded for (int i = 0; i < PlugIn.m_plugins.Count; i++) { System.Reflection.Assembly loadedAssembly = PlugIn.m_plugins[i].Assembly; if (string.Compare(loadedAssembly.FullName, plugin_assembly.FullName, StringComparison.OrdinalIgnoreCase) == 0) { return((int)MonoLoadResult.error_already_loaded); } } // Check version of RhinoCommon that this plug-in uses // Don't allow plug-ins built against earlier versions of RhinoCommon to load bool passesVersionCheck = false; try { System.Reflection.AssemblyName[] referenced_assemblies = plugin_assembly.GetReferencedAssemblies(); for (int i = 0; i < referenced_assemblies.Length; i++) { if (referenced_assemblies[i].Name.Equals("RhinoCommon", StringComparison.OrdinalIgnoreCase)) { Version referenced_version = referenced_assemblies[i].Version; Version this_version = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version; HostUtils.DebugString("Installed RhinoCommon version = {0}", this_version); HostUtils.DebugString("Plug-In built against = {0}", referenced_version); // major and minor MUST match if (referenced_version.Major == this_version.Major && referenced_version.Minor == this_version.Minor) { // At this point the SDK is changing too rapidly to allow for "safe" updates // build of this_version must be == build of referenced version // revision of this_version must be >= build of referenced version if (this_version.Build == referenced_version.Build) { if (this_version.Revision >= referenced_version.Revision) { passesVersionCheck = true; } } } break; } } } catch (Exception ex) { HostUtils.DebugString("Exception while checking versions"); HostUtils.DebugString(ex.Message); } if (!passesVersionCheck) { return((int)MonoLoadResult.error_incompatible_version); } // TODO: Check version of RhinoCommon that this plug-in uses for versioning // At this point, we have determined that this is a RhinoCommon plug-in // We've done all the checking that we can do without actually loading // the DLL ( and resolving links) try { plugin_assembly = System.Reflection.Assembly.LoadFrom(path); } catch (Exception) { plugin_assembly = null; } if (null == plugin_assembly) { return((int)MonoLoadResult.error_unable_to_load); } HostUtils.DebugString("Assembly loaded for real... GetExportedTypes"); Type[] internal_types = null; try { internal_types = plugin_assembly.GetExportedTypes(); } catch (System.Reflection.ReflectionTypeLoadException ex) { HostUtils.DebugString("Caught reflection exception"); Type[] loaded_types = ex.Types; if (loaded_types != null) { HostUtils.DebugString("Got {0} loaded types", loaded_types.Length); for (int i = 0; i < loaded_types.Length; i++) { Type t = loaded_types[i]; if (t != null) { HostUtils.DebugString("{0} - {1}", i, t); } } HostUtils.DebugString(loaded_types.ToString()); } Exception[] e = ex.LoaderExceptions; if (e != null) { HostUtils.DebugString("Got some loader exceptions"); for (int i = 0; i < e.Length; i++) { HostUtils.DebugString(ex.ToString()); internal_types = null; } } } catch (Exception ex) { HostUtils.DebugString("Caught generic exception"); HostUtils.DebugString(ex.ToString()); internal_types = null; // HostUtils.ExceptionReport(ex); } if (null == internal_types) { return((int)MonoLoadResult.error_unable_to_load); } HostUtils.DebugString("{0} Exported Types", internal_types.Length); // walk through list of exported types and find a single class // that derives from PlugIn Type plugin_type = typeof(PlugIn); int type_index = -1; try { for (int i = 0; i < internal_types.Length; i++) { if (plugin_type.IsAssignableFrom(internal_types[i])) { if (type_index >= 0) { return((int)MonoLoadResult.error_create_plugin); } type_index = i; } } } catch (Exception ex) { HostUtils.DebugString("Exception occured while trying to find type that is derived from PlugIn"); HostUtils.ExceptionReport(ex); type_index = -1; } if (type_index < 0) { return((int)MonoLoadResult.error_create_plugin); } plugin_type = internal_types[type_index]; HostUtils.DebugString("Found type derived from PlugIn (" + plugin_type.ToString() + ")"); object[] name = plugin_assembly.GetCustomAttributes(typeof(System.Reflection.AssemblyTitleAttribute), false); string plugin_name; if (name != null && name.Length > 0) { plugin_name = ((System.Reflection.AssemblyTitleAttribute)name[0]).Title; } else { plugin_name = plugin_assembly.GetName().Name; } string plugin_version = plugin_assembly.GetName().Version.ToString(); HostUtils.DebugString(" name = {0}; version = {1}", plugin_name, plugin_version); object[] descriptionAtts = plugin_assembly.GetCustomAttributes(typeof(PlugInDescriptionAttribute), false); if (descriptionAtts != null) { const int idxAddress = 0; const int idxCountry = 1; const int idxEmail = 2; const int idxFax = 3; const int idxOrganization = 4; const int idxPhone = 5; const int idxUpdateUrl = 6; const int idxWebsite = 7; for (int i = 0; i < descriptionAtts.Length; i++) { PlugInDescriptionAttribute description = (PlugInDescriptionAttribute)descriptionAtts[i]; switch (description.DescriptionType) { case DescriptionType.Address: UnsafeNativeMethods.RhMono_SetPlugInLoadString(idxAddress, description.Value); break; case DescriptionType.Country: UnsafeNativeMethods.RhMono_SetPlugInLoadString(idxCountry, description.Value); break; case DescriptionType.Email: UnsafeNativeMethods.RhMono_SetPlugInLoadString(idxEmail, description.Value); break; case DescriptionType.Fax: UnsafeNativeMethods.RhMono_SetPlugInLoadString(idxFax, description.Value); break; case DescriptionType.Organization: UnsafeNativeMethods.RhMono_SetPlugInLoadString(idxOrganization, description.Value); break; case DescriptionType.Phone: UnsafeNativeMethods.RhMono_SetPlugInLoadString(idxPhone, description.Value); break; case DescriptionType.UpdateUrl: UnsafeNativeMethods.RhMono_SetPlugInLoadString(idxUpdateUrl, description.Value); break; case DescriptionType.WebSite: UnsafeNativeMethods.RhMono_SetPlugInLoadString(idxWebsite, description.Value); break; } HostUtils.DebugString(" {0} - {1}", description.DescriptionType, description.Value); } } PlugIn plugin = PlugIn.Create(plugin_type, plugin_name, plugin_version); if (plugin == null) { return((int)MonoLoadResult.error_create_plugin); } // We've created a plug-in so we're pretty committed at this point PlugIn.m_plugins.Add(plugin); // create all commands in the plug-in HostUtils.CreateCommands(plugin); HostUtils.DebugString("Created {0} commands", plugin.GetCommands().Length); HostUtils.DebugString("[MonoHost::LoadPlugIn] - DONE"); return((int)MonoLoadResult.success); }