private void populateDataGridView() { // List all plugins in the UI and enable the update button for out of date plugins var plugins = EncompassHelper.RemoteSession.StartupInfo.Plugins; var updatedSsi = EncompassHelper.SessionObjects.Session.GetSessionStartupInfo(); using (ShadowedCache shadowedCache = new ShadowedCache("Plugins")) { foreach (var pluginInfo in plugins) { // Check if the plugin supports hot updating bool pluginIsHotUpdate = RunningPlugins.Plugins.ContainsKey(pluginInfo.Name); if (pluginIsHotUpdate) { Version fileVersion = shadowedCache.GetFileVersion(pluginInfo.Name); // Find the latest plugin version var serverPluginInfo = updatedSsi.Plugins.FirstOrDefault(f => f.Name == pluginInfo.Name); string[] row = { pluginInfo.Name, fileVersion.ToString(), serverPluginInfo.Version.ToString(), "Update" }; grdPlugins.Rows.Add(row); if (fileVersion == null || serverPluginInfo.Version != fileVersion) { grdPlugins.Rows[grdPlugins.Rows.Count - 1].Cells[1].Style.BackColor = Color.DarkRed; } } } } }
internal static void LoadHotUpdatePlugins() { using (ShadowedCache shadowedCache = new ShadowedCache("Plugins")) { try { var plugins = EncompassHelper.RemoteSession.StartupInfo.Plugins; var assemblies = AppDomain.CurrentDomain.GetAssemblies().ToList(); foreach (var pluginInfo in plugins) { string assemblyPath = shadowedCache.GetFilePath(pluginInfo.Name); string assmName = Path.GetFileNameWithoutExtension(assemblyPath); // The plugin should already be loaded into the assembly cache var appAssm = assemblies.FirstOrDefault(w => w.FullName.Contains(assmName)); if (appAssm != null) { var loadedAssmTypes = appAssm.GetTypes(); var loadedTypesWithAttr = loadedAssmTypes.Where(s => s.GetCustomAttributes(true).Any(a => a.GetType().FullName.Contains("HotUpdatePlugin.Objects.Attributes.HotUpdatePluginAttribute"))); if (loadedTypesWithAttr.Count() > 0) { RunningPlugin rp = new RunningPlugin(); // Load the updated plugin assembly Assembly assembly = RuntimeContext.Current.LoadAssembly(assemblyPath, EncompassHelper.SessionObjects.StartupInfo.RevertPluginChanges); rp.Assembly = assembly; var assmTypes = assembly.GetTypes(); var typesWithAttr = assmTypes.Where(s => s.GetCustomAttributes(true).Any(a => a.GetType().FullName.Contains("HotUpdatePlugin.Objects.Attributes.HotUpdatePluginAttribute"))); List <object> instances = new List <object>(); foreach (Type type in typesWithAttr) { object pluginInstance = type.InvokeMember("", BindingFlags.CreateInstance, null, null, new object[0]); instances.Add(pluginInstance); } rp.Instances = instances; RunningPlugins.Plugins.Add(pluginInfo.Name, rp); } } } } catch (Exception ex) { Logger.HandleError(ex, nameof(PluginLoader), (object)null); } } }
internal static void UpdatePlugin(PluginInfo pluginInfo) { using (ShadowedCache shadowedCache = new ShadowedCache("Plugins")) { Version fileVersion = shadowedCache.GetFileVersion(pluginInfo.Name); Version version = pluginInfo.Version; // Download the latest server plugin and put into the cache if (fileVersion == null || version != fileVersion) { shadowedCache.Put(pluginInfo.Name, EncompassHelper.SessionObjects.ConfigurationManager.GetPluginAssembly(pluginInfo.Name)); } // Dispose of the existing hot updateable plugin RunningPlugins.Plugins.TryGetValue(pluginInfo.Name, out RunningPlugin runningPlugin); if (runningPlugin != null) { foreach (var instance in runningPlugin.Instances) { Type runningType = instance.GetType(); runningType.InvokeMember("Dispose", BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.Public, null, instance, new object[0]); } runningPlugin.Instances = null; runningPlugin.Assembly = null; RunningPlugins.Plugins.Remove(pluginInfo.Name); GC.Collect(); } RunningPlugin rp = new RunningPlugin(); // Load the updated plugin assembly string assemblyPath = shadowedCache.GetFilePath(pluginInfo.Name); Assembly assembly = RuntimeContext.Current.LoadAssembly(assemblyPath, EncompassHelper.SessionObjects.StartupInfo.RevertPluginChanges); rp.Assembly = assembly; var assmTypes = assembly.GetTypes(); var typesWithAttr = assmTypes.Where(s => s.GetCustomAttributes(true).Any(a => a.GetType().FullName.Contains("HotUpdatePlugin.Objects.Attributes.HotUpdatePluginAttribute"))); List <object> instances = new List <object>(); foreach (Type type in typesWithAttr) { object pluginInstance = type.InvokeMember("", BindingFlags.CreateInstance, null, null, new object[0]); instances.Add(pluginInstance); } rp.Instances = instances; RunningPlugins.Plugins.Add(pluginInfo.Name, rp); } }
private void GrdPlugins_CellContentClick(object sender, DataGridViewCellEventArgs e) { var grdPlugins = (DataGridView)sender; if (grdPlugins.Rows.Count > 0 && grdPlugins.Columns[e.ColumnIndex] is DataGridViewButtonColumn && e.RowIndex >= 0) { using (ShadowedCache shadowedCache = new ShadowedCache("Plugins")) { // Get the plugin name string pluginName = (string)grdPlugins.Rows[e.RowIndex].Cells[0].Value; var updatedSsi = EncompassHelper.SessionObjects.Session.GetSessionStartupInfo(); var serverPluginInfo = updatedSsi.Plugins.FirstOrDefault(f => f.Name == pluginName); Version fileVersion = shadowedCache.GetFileVersion(serverPluginInfo.Name); if (fileVersion == null || serverPluginInfo.Version != fileVersion) { if (chkUpdateAll.Checked) { EncompassApplication.Session.DataExchange.PostDataToAll(serverPluginInfo); } else { try { PluginLoader.UpdatePlugin(serverPluginInfo); MessageBox.Show($"Successfuly Hot Updated {serverPluginInfo.Name}"); } catch (Exception ex) { Logger.HandleError(ex, nameof(PluginHotUpdate_Form), (object)null); MessageBox.Show($"Failed to Hot Update {serverPluginInfo.Name}{Environment.NewLine}Error:{Environment.NewLine}{ex.Message}"); } } } else { MessageBox.Show($"Client Version [{fileVersion}] matches Server Version [{serverPluginInfo.Version}]{Environment.NewLine}{Environment.NewLine}Update will not be run"); } } refreshGrid(); } }