diff --git a/dnSpy/dnSpy.Contracts.DnSpy/App/IAppCommandLineArgs.cs b/dnSpy/dnSpy.Contracts.DnSpy/App/IAppCommandLineArgs.cs index 8856620532..f4e044d430 100644 --- a/dnSpy/dnSpy.Contracts.DnSpy/App/IAppCommandLineArgs.cs +++ b/dnSpy/dnSpy.Contracts.DnSpy/App/IAppCommandLineArgs.cs @@ -90,6 +90,9 @@ public interface IAppCommandLineArgs { /// Attach to this process name, unless it's empty. Can contain wildcards. string DebugAttachProcess { get; } + /// Additional directory to check for extensions. + string ExtraExtensionDirectory { get; } + /// /// Returns true if the argument is present /// diff --git a/dnSpy/dnSpy/MainApp/App.xaml.cs b/dnSpy/dnSpy/MainApp/App.xaml.cs index d5944f86a9..d6773e6c28 100644 --- a/dnSpy/dnSpy/MainApp/App.xaml.cs +++ b/dnSpy/dnSpy/MainApp/App.xaml.cs @@ -96,6 +96,7 @@ static void ShowException(Exception? ex) { Stopwatch? startupStopwatch; public App(bool readSettings, Stopwatch startupStopwatch) { resourceManagerTokenCacheImpl = new ResourceManagerTokenCacheImpl(); + args = new AppCommandLineArgs(); // PERF: Init MEF on a BG thread. Results in slightly faster startup, eg. InitializeComponent() becomes a 'free' call on this UI thread initializeMEFTask = Task.Run(() => InitializeMEF(readSettings, useCache: readSettings)); @@ -103,7 +104,6 @@ public App(bool readSettings, Stopwatch startupStopwatch) { resourceManagerTokenCacheImpl.TokensUpdated += ResourceManagerTokenCacheImpl_TokensUpdated; ResourceHelper.SetResourceManagerTokenCache(resourceManagerTokenCacheImpl); - args = new AppCommandLineArgs(); AppDirectories.SetSettingsFilename(args.SettingsFilename); AddAppContextFixes(); @@ -324,10 +324,14 @@ Assembly[] GetAssemblies() { Assembly[] LoadExtensionAssemblies() { var dir = AppDirectories.BinDirectory; + var unsortedFiles = GetExtensionFiles(dir); + if (!(args.ExtraExtensionDirectory is null)) + unsortedFiles = unsortedFiles.Concat(GetExtensionFiles(args.ExtraExtensionDirectory)); + // Load the modules in a predictable order or multicore-JIT could stop recording. See // "Understanding Background JIT compilation -> What can go wrong with background JIT compilation" // in the PerfView docs for more info. - var files = GetExtensionFiles(dir).OrderBy(a => a, StringComparer.OrdinalIgnoreCase).ToArray(); + var files = unsortedFiles.OrderBy(a => a, StringComparer.OrdinalIgnoreCase).ToArray(); #if NETCOREAPP foreach (var file in files) netCoreAssemblyLoader.AddSearchPath(Path.GetDirectoryName(file)!); diff --git a/dnSpy/dnSpy/MainApp/AppCommandLineArgs.cs b/dnSpy/dnSpy/MainApp/AppCommandLineArgs.cs index 87c55e41a8..47a8e15999 100644 --- a/dnSpy/dnSpy/MainApp/AppCommandLineArgs.cs +++ b/dnSpy/dnSpy/MainApp/AppCommandLineArgs.cs @@ -49,6 +49,7 @@ sealed class AppCommandLineArgs : IAppCommandLineArgs { public uint DebugEvent { get; } public ulong JitDebugInfo { get; } public string DebugAttachProcess { get; } + public string ExtraExtensionDirectory { get; } readonly Dictionary userArgs = new Dictionary(); readonly List filenames = new List(); @@ -194,6 +195,11 @@ public AppCommandLineArgs(string[] args) { i++; break; + case "--extension-directory": + ExtraExtensionDirectory = GetFullPath(next); + i++; + break; + default: int sepIndex = arg.IndexOf(ARG_SEP); string argName, argValue;