diff --git a/doc/devdocs/modules/launcher/new-plugin-checklist.md b/doc/devdocs/modules/launcher/new-plugin-checklist.md index 3554e3af47..c3fcab39a8 100644 --- a/doc/devdocs/modules/launcher/new-plugin-checklist.md +++ b/doc/devdocs/modules/launcher/new-plugin-checklist.md @@ -3,6 +3,7 @@ - [ ] Microsoft plugin project name pattern: `Microsoft.PowerToys.Run.Plugin.{PluginName}` - [ ] Community plugin project name pattern: `Community.PowerToys.Run.Plugin.{PluginName}` - [ ] The project file should import `Version.props` and specify `$(Version).0` +- [ ] If the plugin uses any 3rd party dependencies the project file should import `DynamicPlugin.props` - [ ] Make sure `*.csproj` specify only x64 platform target - [ ] The plugin has to contain a `plugin.json` file of the following format in its root folder ``` @@ -17,7 +18,8 @@ "Website": "https://aka.ms/powertoys", "ExecuteFileName": string, // Should be {Type}.PowerToys.Run.Plugin.{PluginName}.dll "IcoPathDark": string, // Path to dark theme icon. The path is relative to the root plugin folder - "IcoPathLight": string // Path to light theme icon. The path is relative to the root plugin folder + "IcoPathLight": string // Path to light theme icon. The path is relative to the root plugin folder + "DynamicLoading": bool // Sets whether the plugin should dynamically load any dependencies isolated from the core application. } ``` - [ ] Make sure your `Main` class contains a public, static string property for the `PluginID`. The plugin id has to be the same as the one in the `plugin.json`file. diff --git a/src/modules/launcher/Plugins/DynamicPlugin.props b/src/modules/launcher/Plugins/DynamicPlugin.props new file mode 100644 index 0000000000..746e635e8d --- /dev/null +++ b/src/modules/launcher/Plugins/DynamicPlugin.props @@ -0,0 +1,12 @@ + + + + true + + + + + false + + + diff --git a/src/modules/launcher/Wox.Plugin/PluginLoadContext.cs b/src/modules/launcher/Wox.Plugin/PluginLoadContext.cs new file mode 100644 index 0000000000..03268dd49d --- /dev/null +++ b/src/modules/launcher/Wox.Plugin/PluginLoadContext.cs @@ -0,0 +1,44 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Linq; +using System.Reflection; +using System.Runtime.Loader; + +namespace Wox.Plugin +{ + internal class PluginLoadContext : AssemblyLoadContext + { + private AssemblyDependencyResolver _resolver; + + public PluginLoadContext(string pluginPath) + { + _resolver = new AssemblyDependencyResolver(pluginPath); + } + + protected override Assembly Load(AssemblyName assemblyName) + { + string assemblyPath = _resolver.ResolveAssemblyToPath(assemblyName); + if (assemblyPath != null) + { + var existingAssembly = Default.Assemblies.FirstOrDefault(x => x.FullName == assemblyName.FullName); + return existingAssembly ?? LoadFromAssemblyPath(assemblyPath); + } + + return null; + } + + protected override IntPtr LoadUnmanagedDll(string unmanagedDllName) + { + string libraryPath = _resolver.ResolveUnmanagedDllToPath(unmanagedDllName); + if (libraryPath != null) + { + return LoadUnmanagedDllFromPath(libraryPath); + } + + return IntPtr.Zero; + } + } +} diff --git a/src/modules/launcher/Wox.Plugin/PluginMetadata.cs b/src/modules/launcher/Wox.Plugin/PluginMetadata.cs index a9461f0181..6ee9703bd0 100644 --- a/src/modules/launcher/Wox.Plugin/PluginMetadata.cs +++ b/src/modules/launcher/Wox.Plugin/PluginMetadata.cs @@ -65,6 +65,8 @@ namespace Wox.Plugin public string IcoPathLight { get; set; } + public bool DynamicLoading { get; set; } + public override string ToString() { return Name; diff --git a/src/modules/launcher/Wox.Plugin/PluginPair.cs b/src/modules/launcher/Wox.Plugin/PluginPair.cs index 6fd0834483..4c1fdc592e 100644 --- a/src/modules/launcher/Wox.Plugin/PluginPair.cs +++ b/src/modules/launcher/Wox.Plugin/PluginPair.cs @@ -4,6 +4,7 @@ using System; using System.Diagnostics; +using System.IO; using System.Linq; using System.Reflection; using System.Runtime.Loader; @@ -153,7 +154,15 @@ namespace Wox.Plugin try { - _assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(Metadata.ExecuteFilePath); + if (Metadata.DynamicLoading) + { + var loadContext = new PluginLoadContext(Metadata.ExecuteFilePath); + _assembly = loadContext.LoadFromAssemblyName(new AssemblyName(Path.GetFileNameWithoutExtension(Metadata.ExecuteFilePath))); + } + else + { + _assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(Metadata.ExecuteFilePath); + } } catch (Exception e) {