/// <summary>Uninstall <paramref name="pluginInstance" />. The plugin will be stopped if it is running.</summary> /// <param name="pluginInstance">The plugin to be uninstalled</param> /// <returns></returns> /// <exception cref="ArgumentNullException"></exception> /// <exception cref="ArgumentException"> /// When <paramref name="pluginInstance" /> is a Development /// plugin /// </exception> public async Task <bool> UninstallPluginAsync(TPluginInstance pluginInstance) { if (pluginInstance == null) { throw new ArgumentNullException(nameof(pluginInstance)); } if (pluginInstance.IsDevelopment) { throw new ArgumentException($"Cannot uninstall a development plugin"); } if (await StopPlugin(pluginInstance) == false) { LogAdapter.Warning($"Failed to stop plugin {pluginInstance.Package.Id}, aborting uninstallation."); return(false); } bool success; using (await pluginInstance.Lock.LockAsync()) using (await PMLock.WriterLockAsync()) { success = await PackageManager.UninstallAsync(pluginInstance.Package); if (success) { AllPluginsInternal.Remove(pluginInstance); } } return(success); }
/// <summary>Starts all enabled plugins.</summary> /// <returns>Whether all plugins started successfully</returns> public async Task <bool> StartPlugins() { try { LogTo.Information($"Starting all {AllPluginsInternal.Count(p => p.IsEnabled)} enabled plugins out of {AllPluginsInternal.Count}."); var plugins = AllPluginsInternal.Where(pi => pi.IsEnabled) .OrderBy(pi => pi.IsDevelopment) .DistinctBy(pi => pi.Package.Id); var startTasks = plugins.Select(p => StartPlugin(p)).ToList(); var startTasksRes = await Task.WhenAll(startTasks); var successCount = startTasksRes.Count(success => success); var failureCount = startTasksRes.Length - successCount; LogTo.Information($"{successCount} started successfully, {failureCount} failed to start."); return(failureCount == 0); } catch (Exception ex) { LogTo.Warning(ex, "Exception caught while starting plugins."); throw; } }
/// <summary> /// Verifies that <paramref name="packageName" /> can be found in the local packages, and /// adds it to the list of loaded plugins. Called by InstallPluginAsync() after a /// successful Install result from the <see cref="PackageManager" />. /// (!!) A lock on PMLock should have been acquired before calling this method. /// </summary> /// <param name="packageName">The installed package name</param> /// <returns>Whether the package has been successfully installed</returns> private bool PostInstallPlugin(string packageName) { var pluginPackage = PackageManager.FindInstalledPluginById(packageName); if (pluginPackage == null) { throw new InvalidOperationException($"Package {packageName} installed successfully but couldn't be found"); } AllPluginsInternal.Add(CreatePluginInstance(pluginPackage)); return(true); }
/// <summary>Stops all running plugins, clears all loaded plugins, scans and load available plugin</summary> /// <returns>The number of plugin loaded</returns> protected virtual async Task <int> RefreshPlugins() { try { LogTo.Information("Refreshing plugins."); await StopPlugins(); AllPluginsInternal.Clear(); ScanLocalPlugins(true) .Select(CreatePluginInstance) .Distinct() .ForEach(pi => AllPluginsInternal.Add(pi)); LogTo.Information($"Found {AllPluginsInternal.Count} plugins."); return(AllPluginsInternal.Count); } catch (Exception ex) { LogTo.Warning(ex, "Exception caught while refreshing plugins."); throw; } }