// Public methods public void FindPlugin(string path) { Platform.CheckForNullReference(path, "path"); Platform.CheckForEmptyString(path, "path"); try { Assembly asm = LoadAssembly(path); Attribute[] attrs = Attribute.GetCustomAttributes(asm); foreach (Attribute attr in attrs) { if (attr is PluginAttribute) { _pluginFiles.Add(path); break; } } } catch (BadImageFormatException e) { // Encountered an unmanaged DLL in the plugin directory; this is okay // but we'll log it anyway Platform.Log(LogLevel.Debug, SR.LogFoundUnmanagedDLL, e.FileName); } catch (FileNotFoundException e) { Platform.Log(LogLevel.Error, e, "File not found while loading plugin: {0}", path); throw; } catch (Exception e) { Platform.Log(LogLevel.Error, e, "Error loading plugin: {0}", path); throw; } }
private string[] FindPlugins(string path) { Platform.CheckForNullReference(path, "path"); Platform.CheckForEmptyString(path, "path"); AppDomain domain = null; string[] pluginFiles = null; try { EventsHelper.Fire(_pluginProgressEvent, this, new PluginLoadedEventArgs(SR.MessageFindingPlugins, null)); // Create a secondary AppDomain where we can load all the DLLs in the plugin directory #if MONO domain = AppDomain.CreateDomain("Secondary"); #else Evidence evidence = new Evidence( new object[] { new Zone(SecurityZone.MyComputer) }, new object[] { }); PermissionSet permissions = SecurityManager.ResolvePolicy(evidence); AppDomainSetup setup = new AppDomainSetup(); setup.ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase; #region fix plugin loading problem in ASP.NET // Apparently we need to use the same lookup paths from the original app domain // if the application is launched by ASP.NET. The original app domain // has reference to the "bin" folder where all reference dll's in the webpage are kept (auto copied by // VS.NET when you add references). If this is not set, calling // // domain.CreateInstanceAndUnwrap(asm.FullName, "ClearCanvas.Common.PluginFinder") // // will cause file-not-found exception // // To be safe, it's best to copy the original PrivateBinPath instead of hardcoding "Bin" // setup.PrivateBinPath = AppDomain.CurrentDomain.SetupInformation.PrivateBinPath; setup.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile; #endregion domain = AppDomain.CreateDomain( "Secondary", evidence, setup, permissions, new StrongName[] { }); #endif Assembly asm = Assembly.GetExecutingAssembly(); // Instantiate the finder in the secondary domain PluginFinder finder = domain.CreateInstanceAndUnwrap(asm.FullName, "ClearCanvas.Common.PluginFinder") as PluginFinder; // Assign the FileProcessor's delegate to the finder FileProcessor.ProcessFile del = new FileProcessor.ProcessFile(finder.FindPlugin); // Process the plugin directory FileProcessor.Process(path, "*.dll", del, true); // Get the list of legitimate plugin DLLs pluginFiles = finder.PluginFiles; } catch (Exception e) { Platform.Log(LogLevel.Error, e); throw; // TH (Oct 5, 2007) replaced "throw e" with "throw". "throw e" produces a new exception stack. We want to know where the original exception occurs instead } finally { // Unload the domain so that we free up memory used on loading non-plugin DLLs if (domain != null) { AppDomain.Unload(domain); } if (pluginFiles == null) { throw new PluginException(SR.ExceptionNoPluginsFound); } } return(pluginFiles); }