/// <summary> /// Выгрузить работающее дополнение /// </summary> /// <param name="info">Выгружаемое дополнение</param> private void UnloadAddon(RunningAddonInfo info, bool showError = true) { try { lock (this.runningAddons) { this.runningAddons.Remove(info.Instanse); } info.Instanse.Dispose(); AppDomain.Unload(info.Domain); } catch (ThreadAbortException) { } catch (AppDomainUnloadedException) { } catch (Exception exc) { if (showError) { MessageBox.Show(string.Format(String.Format("{0} {1} {2}", Resources.AddonError, exc.Message, exc.GetType()), GetLocalizationInfoForAddon(info.Info).Title), Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } } }
/// <summary> /// Запустить дополнение /// </summary> /// <param name="info">Запускаемое дополнение</param> internal void RunAddon(AddonInformation info) { var thread = new Thread(arg => { AppDomain domain = null; Addon addon; try { domain = AppDomain.CreateDomain("Addon", AppDomain.CurrentDomain.Evidence, new AppDomainSetup { ApplicationBase = Application.StartupPath, PrivateBinPath = Path.GetDirectoryName(info.Path) }); var loader = (ObjectLoader)domain.CreateInstanceFromAndUnwrap(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "CIRCe.Base.dll"), "CIRCe.Base.ObjectLoader"); addon = (Addon)loader.LoadObject(info.Path, info.Info.AddonType); //domain.CreateInstanceFromAndUnwrap(info.Path, info.Info.AddonType); if (Settings.Default.SearchForAddons == CheckState.Checked) // Проверяем наличие обновления { if (addon.IsUpdateNeeded() && MessageBox.Show(string.Format("Дополнение \"{0}\" сообщает, что оно нуждается в обновлении. Обновить его?", GetLocalizationInfoForAddon(info).Title), Application.ProductName, MessageBoxButtons.YesNo, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.Yes) { var updatePath = addon.GetUpdateUri(); addon.Dispose(); AppDomain.Unload(domain); UpdateAddon(info, updatePath); return; } } domain.UnhandledException += domain_UnhandledException; } catch (Exception e) { MessageBox.Show(string.Format("Ошибка запуска дополнения {0}: {1}", GetLocalizationInfoForAddon(info).Title, e.Message), Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Error); if (domain != null) { AppDomain.Unload(domain); } return; } //SecurityPermission perm = new SecurityPermission(SecurityPermissionFlag.UnmanagedCode); //perm.Deny(); var addonInfo = new RunningAddonInfo { Domain = domain, MainThread = Thread.CurrentThread, Info = info, Instanse = addon }; lock (this.runningAddons) { this.runningAddons[addon] = addonInfo; } var showError = true; try { addon.Run(this.application); } catch (TargetInvocationException) { MessageBox.Show(string.Format(String.Format("{0} {1}", Resources.AddonError, "Нельзя подписываться на события Цирцеи в дополнении напрямую. Используйте метод Wrap или класс EventWrapper"), info.LocalizedInfos[0].Title), Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Exclamation); showError = false; } catch (Exception exc) { MessageBox.Show(string.Format(String.Format("{0} {1} {2}", Resources.AddonError, exc.Message, exc.GetType()), GetLocalizationInfoForAddon(info).Title), Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Exclamation); showError = false; } finally { UnloadAddon(addonInfo, showError: showError); } }) { IsBackground = true }; thread.SetApartmentState(ApartmentState.STA); thread.Start(); }