private static void Unload(string path) { instance.Print("Unloading scripts in \"" + path + "\"..."); AppDomain oldAppDomain = null; List <IServerScript> oldscripts = new List <IServerScript>(); if (_scripts.ContainsKey(path)) { oldscripts = _scripts[path]; _scripts.Remove(path); oldAppDomain = SeparateAppDomain.Extract(path); } instance.Print(oldscripts.Count + " script(s) unloaded from \"" + path + "\"."); instance.Print(""); ScriptTimer[] timers; lock (ScriptTimers) timers = ScriptTimers.ToArray(); foreach (IServerScript iscript in oldscripts) { foreach (ScriptTimer st in timers.Where(st => st.caller == iscript)) { st.Dispose(); } lock (scripteventhandlers) { if (scripteventhandlers.ContainsKey(iscript)) { foreach (string eventname in scripteventhandlers[iscript].Keys) { try { instance.RemoveAllEventHandlers((ServerScript)iscript, eventname); ((ServerScript)iscript).RemoveAllEventHandlers(eventname); } catch (Exception e) { instance.Print(PrintType.Error, "Failed to remove \"" + iscript.Name + "\"'s event handlers for event \"" + eventname + "\"."); instance.PrintException(e); } } scripteventhandlers[iscript].Clear(); scripteventhandlers.Remove(iscript); } } ServerScript script = ((ServerScript)iscript); if (script.timer != null) { script.timer.Dispose(); } try { iscript.Unload(); } catch (Exception e) { instance.Print(PrintType.Error, "\"" + iscript.Name + "\"'s Unload() failed."); instance.PrintException(e); } ((ILease)script.GetLifetimeService()).Unregister(instance); } lock (scripteventhandlers) scripteventhandlers.Clear(); //assemblies.Clear(); if (oldAppDomain != null) { AppDomain.Unload(oldAppDomain); } }
private static void Load(string path) { instance.Print("Loading scripts in \"" + path + "\"..."); foreach (string file in Directory.GetFiles(path, "*.dll")) { if (AssemblyName.GetAssemblyName(file).Name == "ServerWrapper") { instance.Print("Found ServerWrapper assembly in Scripts folder. Removing..."); try { File.Delete(file); } catch (Exception e) { instance.Print(PrintType.Warning, "Failed to remove ServerWrapper assembly from Scripts folder, this may cause issues."); instance.PrintException(e); } } } /*if (Directory.GetFiles(path, "*.cs").Length > 0) * { * string localassembly = typeof(ServerScript).Assembly.Location; * AppDomain domain = AppDomain.CreateDomain("Test"); * domain.DoCallBack(() => * { * System.CodeDom.Compiler.CompilerParameters options = new System.CodeDom.Compiler.CompilerParameters(); * options.CompilerOptions = "/optimize /unsafe"; * options.GenerateInMemory = true; * //options.GenerateInMemory = false; * options.IncludeDebugInformation = true; * options.ReferencedAssemblies.AddRange(new string[] * { * "System.dll", * "System.Core.dll", * "System.Drawing.dll", * "System.Windows.Forms.dll", * "System.XML.dll", * "System.XML.Linq.dll", * localassembly, * "System.ComponentModel.Composition.dll" * }); * * System.CodeDom.Compiler.CodeDomProvider compiler = new Microsoft.CSharp.CSharpCodeProvider(); * * foreach (string file in Directory.GetFiles(path, "*.cs")) * { * options.OutputAssembly = Path.ChangeExtension(file, ".dll"); * * System.CodeDom.Compiler.CompilerResults result = compiler.CompileAssemblyFromFile(options, file); * * if (!result.Errors.HasErrors) * { * instance.RconPrint((result.CompiledAssembly == null).ToString()); * instance.RconPrint(result.PathToAssembly); * } * else * { * string errors = ""; * * foreach (System.CodeDom.Compiler.CompilerError error in result.Errors) errors += " at line " + error.Line + ": " + error.ErrorText + "\r\n"; * * instance.RconPrint("[ERROR] Failed to compile '" + Path.GetFileName(file) + "' with " + result.Errors.Count + " error(s):\r\n" + errors.ToString()); * } * } * }); * * AppDomain.Unload(domain); * }*/ MefLoader mefLoader = SeparateAppDomain.CreateInstance <MefLoader>(path, path); mefLoader.Domain.UnhandledException += (sender, e) => { instance.Print(PrintType.Error, "Unhandled exception occured in script."); instance.PrintException((Exception)e.ExceptionObject); }; /*mefLoader.Domain.AssemblyResolve += (sender, e) => * { * * };*/ List <IServerScript> scripts = mefLoader.Load <IServerScript>(); if (scripts.Count == 0) { SeparateAppDomain.Delete(path); instance.Print("No scripts found in \"" + path + "\"."); return; } //assemblies.Clear(); _scripts.Add(path, scripts); instance.Print(scripts.Count + " script(s) found in \"" + path + "\"."); instance.Print(""); // Sorting logic from ScriptHookVDotNet Dictionary <IServerScript, List <string> > graph = new Dictionary <IServerScript, List <string> >(); Queue <IServerScript> sorted = new Queue <IServerScript>(); foreach (IServerScript script in scripts) { graph.Add(script, new List <string>(script.Dependencies)); } while (graph.Count > 0) { IServerScript s = null; foreach (var kv in graph) { if (kv.Value.Count == 0) { s = kv.Key; break; } } if (s == null) { instance.Print(PrintType.Fatal, "Detected a circular script dependency. Aborting..."); instance.Print(""); return; } sorted.Enqueue(s); graph.Remove(s); foreach (var kv in graph) { kv.Value.Remove(s.TypeName); } } if (graph.Count == 0) { LoadScripts(sorted); } }