using System.Diagnostics; using System.Reflection; using Sandbox.Graphics.GUI; using VRage; namespace PluginLoader.Data; public class LocalPlugin : PluginData { private LocalPlugin() { } public LocalPlugin(string dll) { Id = dll; Status = PluginStatus.None; } public override string Source => MyTexts.GetString(MyCommonTexts.Local); public override string Id { get => base.Id; set { base.Id = value; if (File.Exists(value)) FriendlyName = Path.GetFileName(value); } } public override Assembly? GetAssembly() { if (!File.Exists(Id)) return null; //prevent random unloading if being used by another process int maxRetries = 10; while (maxRetries > 0) { try { AppDomain.CurrentDomain.AssemblyResolve += LoadFromSameFolder; var a = Assembly.LoadFile(Id); Version = a?.GetName()?.Version ?? Version; return a; } catch (IOException) { LogFile.Log.Debug($"Waiting to load {Id} because it's being used by another process"); Thread.Sleep(250); maxRetries--; } } return null; } public override string ToString() { return Id; } public override void Show() { var file = Path.GetFullPath(Id); if (File.Exists(file)) Process.Start("explorer.exe", $"/select, \"{file}\""); } private Assembly? LoadFromSameFolder(object sender, ResolveEventArgs args) { if (args.RequestingAssembly?.IsDynamic ?? false) return null; if (args.Name.Contains("0Harmony") || args.Name.Contains("SEPluginManager")) return null; var location = args.RequestingAssembly?.Location; if (string.IsNullOrWhiteSpace(location) || !Path.GetFullPath(location) .StartsWith(Path.GetDirectoryName(Id)!, StringComparison.OrdinalIgnoreCase)) return null; var folderPath = Path.GetDirectoryName(Id); if (string.IsNullOrEmpty(folderPath)) return null; var assemblyPath = Path.Combine(folderPath, new AssemblyName(args.Name).Name + ".dll"); if (!File.Exists(assemblyPath)) return null; var assembly = Assembly.LoadFile(assemblyPath); LogFile.Log.Debug("Resolving " + assembly.GetName().Name + " for " + args.RequestingAssembly?.FullName, false); var main = Main.Instance; if (!main.Config.IsEnabled(assemblyPath)) main.List.Remove(assemblyPath); return assembly; } public override void GetDescriptionText(MyGuiControlMultilineText textbox) { textbox.Visible = false; textbox.Clear(); } }