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();
            }
        }