mirror of
https://github.com/tribufu/ServerManagers
synced 2026-05-06 15:17:34 +00:00
1. Profile name has been converted to a droplist and is now populated with the Server Manager Profile Names for selection.
293 lines
8.7 KiB
C#
293 lines
8.7 KiB
C#
using ServerManagerTool.Plugin.Common.Delegates;
|
|
using ServerManagerTool.Plugin.Common.Lib;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Windows;
|
|
|
|
namespace ServerManagerTool.Plugin.Common
|
|
{
|
|
public sealed class PluginHelper : IDisposable
|
|
{
|
|
private const string PLUGINFILE_FOLDER = "Plugins";
|
|
private const string PLUGINFILE_EXTENSION = "dll";
|
|
|
|
private static volatile PluginHelper _instance;
|
|
private static readonly object _syncLock = new object();
|
|
|
|
private readonly Object _syncLockProcessAlert = new Object();
|
|
private readonly Object _syncLockFetchProfiles = new Object();
|
|
private FetchProfilesDelegate _fetchProfilesCallback;
|
|
private bool _disposed;
|
|
|
|
private PluginHelper()
|
|
{
|
|
BetaEnabled = false;
|
|
Plugins = new ObservableCollection<PluginItem>();
|
|
}
|
|
|
|
public static PluginHelper Instance
|
|
{
|
|
get
|
|
{
|
|
if (_instance != null)
|
|
return _instance;
|
|
|
|
lock(_syncLock)
|
|
{
|
|
if (_instance == null)
|
|
_instance = new PluginHelper();
|
|
}
|
|
return _instance;
|
|
}
|
|
}
|
|
|
|
public static string PluginFolder
|
|
{
|
|
get
|
|
{
|
|
var folder = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location ?? Environment.CurrentDirectory);
|
|
return Path.Combine(folder, PLUGINFILE_FOLDER);
|
|
}
|
|
}
|
|
|
|
internal bool BetaEnabled
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
|
|
public ObservableCollection<PluginItem> Plugins
|
|
{
|
|
get;
|
|
private set;
|
|
}
|
|
|
|
internal void AddPlugin(string folder, string pluginFile)
|
|
{
|
|
if (!CheckPluginFile(pluginFile))
|
|
throw new PluginException("The selected file does not contain server manager plugins or is for a previous version of server manager.");
|
|
|
|
var pluginFolder = Path.Combine(folder, PLUGINFILE_FOLDER);
|
|
if (!Directory.Exists(pluginFolder))
|
|
Directory.CreateDirectory(pluginFolder);
|
|
|
|
var newPluginFile = Path.Combine(pluginFolder, $"{Path.GetFileName(pluginFile)}");
|
|
if (File.Exists(newPluginFile))
|
|
throw new PluginException("A file with the same name already exists, delete the existing file and try again.");
|
|
|
|
File.Copy(pluginFile, newPluginFile, true);
|
|
|
|
LoadPlugin(newPluginFile);
|
|
}
|
|
|
|
internal bool CheckPluginFile(string pluginFile)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(pluginFile))
|
|
return false;
|
|
if (!File.Exists(pluginFile))
|
|
return false;
|
|
|
|
Assembly assembly = Assembly.Load(File.ReadAllBytes(pluginFile));
|
|
if (assembly == null)
|
|
return false;
|
|
|
|
Type[] types;
|
|
|
|
try
|
|
{
|
|
types = assembly.GetTypes();
|
|
}
|
|
catch
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (types.Length == 0)
|
|
return false;
|
|
|
|
// check if the file contains a plugin
|
|
foreach (Type type in types)
|
|
{
|
|
if (type.GetInterface(typeof(IPlugin).Name) != null)
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
internal void DeleteAllPlugins()
|
|
{
|
|
for (int index = Plugins.Count - 1; index >= 0; index--)
|
|
{
|
|
var pluginFile = Plugins[index].PluginFile;
|
|
|
|
Plugins.RemoveAt(index);
|
|
|
|
if (File.Exists(pluginFile))
|
|
File.Delete(pluginFile);
|
|
}
|
|
}
|
|
|
|
internal void DeletePlugin(string pluginFile)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(pluginFile))
|
|
return;
|
|
|
|
for (int index = Plugins.Count - 1; index >= 0; index--)
|
|
{
|
|
if (Plugins[index].PluginFile.Equals(pluginFile, StringComparison.OrdinalIgnoreCase))
|
|
Plugins.RemoveAt(index);
|
|
}
|
|
|
|
if (File.Exists(pluginFile))
|
|
File.Delete(pluginFile);
|
|
}
|
|
|
|
public IList<Profile> FetchProfileList()
|
|
{
|
|
lock (_syncLockFetchProfiles)
|
|
{
|
|
return _fetchProfilesCallback?.Invoke() ?? new List<Profile>();
|
|
}
|
|
}
|
|
|
|
internal void LoadPlugin(string pluginFile)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(pluginFile))
|
|
return;
|
|
if (!File.Exists(pluginFile))
|
|
return;
|
|
|
|
Assembly assembly = Assembly.Load(File.ReadAllBytes(pluginFile));
|
|
if (assembly == null)
|
|
return;
|
|
|
|
Type[] types;
|
|
|
|
try
|
|
{
|
|
types = assembly.GetTypes();
|
|
}
|
|
catch
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (types.Length == 0)
|
|
return;
|
|
|
|
// check if the file contains one or more plugins
|
|
foreach (Type type in types)
|
|
{
|
|
try
|
|
{
|
|
if (type.GetInterface(typeof(IAlertPlugin).Name) != null)
|
|
{
|
|
var plugin = assembly.CreateInstance(type.FullName) as IAlertPlugin;
|
|
if (plugin != null && plugin.Enabled)
|
|
{
|
|
if (type.GetInterface(typeof(IBeta).Name) != null)
|
|
((IBeta)plugin).BetaEnabled = BetaEnabled;
|
|
plugin.Initialize();
|
|
|
|
Plugins.Add(new PluginItem { Plugin = plugin, PluginFile = pluginFile, PluginType = nameof(IAlertPlugin) });
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Debug.WriteLine($"ERROR: {nameof(LoadPlugin)} - {type.FullName}\r\n{ex.Message}");
|
|
}
|
|
}
|
|
}
|
|
|
|
internal void LoadPlugins(string folder, bool ClearExisting)
|
|
{
|
|
if (ClearExisting)
|
|
Plugins.Clear();
|
|
|
|
var pluginFolder = Path.Combine(folder, PLUGINFILE_FOLDER);
|
|
if (string.IsNullOrWhiteSpace(pluginFolder))
|
|
return;
|
|
if (!Directory.Exists(pluginFolder))
|
|
return;
|
|
|
|
var pluginFiles = Directory.GetFiles(pluginFolder, $"*.{PLUGINFILE_EXTENSION}");
|
|
foreach (var pluginFile in pluginFiles)
|
|
{
|
|
LoadPlugin(pluginFile);
|
|
}
|
|
}
|
|
|
|
internal void OpenConfigForm(string pluginCode, Window owner)
|
|
{
|
|
if (Plugins == null)
|
|
return;
|
|
|
|
var pluginItem = Plugins.FirstOrDefault(p => p.Plugin.PluginCode.Equals(pluginCode, StringComparison.OrdinalIgnoreCase));
|
|
OpenConfigForm(pluginItem.Plugin, owner);
|
|
}
|
|
|
|
internal void OpenConfigForm(IPlugin plugin, Window owner)
|
|
{
|
|
if (plugin == null || !plugin.Enabled || !plugin.HasConfigForm)
|
|
return;
|
|
|
|
plugin.OpenConfigForm(owner);
|
|
}
|
|
|
|
internal bool ProcessAlert(AlertType alertType, string profileName, string alertMessage)
|
|
{
|
|
if (Plugins == null || Plugins.Count == 0 || string.IsNullOrWhiteSpace(alertMessage))
|
|
return false;
|
|
|
|
var plugins = Plugins.Where(p => (p.PluginType is nameof(IAlertPlugin)) && (p.Plugin?.Enabled ?? false));
|
|
if (plugins.Count() == 0)
|
|
return false;
|
|
|
|
lock (_syncLockProcessAlert)
|
|
{
|
|
var message = alertMessage.Replace("\\r\\n", "\\n");
|
|
message = message.Replace("\\n", "\n");
|
|
|
|
foreach (var pluginItem in plugins)
|
|
{
|
|
((IAlertPlugin)pluginItem.Plugin).HandleAlert(alertType, profileName, message.ToString());
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
internal void SetFetchProfileCallback(FetchProfilesDelegate callback)
|
|
{
|
|
_fetchProfilesCallback = callback;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
Dispose(true);
|
|
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
|
|
private void Dispose(bool disposing)
|
|
{
|
|
if (_disposed)
|
|
return;
|
|
|
|
if (disposing)
|
|
{
|
|
_fetchProfilesCallback = null;
|
|
_instance = null;
|
|
}
|
|
|
|
_disposed = true;
|
|
}
|
|
}
|
|
}
|