diff --git a/Il2CppInspector.Common/Plugins/PluginManager.cs b/Il2CppInspector.Common/Plugins/PluginManager.cs index 22a15eb..8153c3b 100644 --- a/Il2CppInspector.Common/Plugins/PluginManager.cs +++ b/Il2CppInspector.Common/Plugins/PluginManager.cs @@ -50,6 +50,13 @@ namespace Il2CppInspector public string Operation { get; set; } } + // Event arguments for option handler + public class PluginOptionErrorEventArgs : PluginErrorEventArgs + { + // The option causing the problem + public IPluginOption Option { get; set; } + } + // Event arguments for the status handler public class PluginStatusEventArgs : EventArgs { @@ -247,6 +254,24 @@ namespace Il2CppInspector return eventInfo; } + // Validate all options for enabled plugins + public static PluginOptionsChangedEventInfo ValidateAllOptions() { + // Enforce this by causing each option's setter to run + var eventInfo = new PluginOptionsChangedEventInfo(); + + foreach (var plugin in EnabledPlugins) + foreach (var option in plugin.Options) + try { + option.Value = option.Value; + } + catch (Exception ex) { + eventInfo.Error = new PluginOptionErrorEventArgs { Plugin = plugin, Exception = ex, Option = option, Operation = "options update" }; + ErrorHandler?.Invoke(AsInstance, eventInfo); + break; + } + return eventInfo; + } + // Try to cast each enabled plugin to a specific interface type, and for those supporting the interface, execute the supplied delegate // Errors will be forwarded to the error handler internal static E Try(Action action) where E : PluginEventInfo, new() diff --git a/Il2CppInspector.GUI/App.xaml.cs b/Il2CppInspector.GUI/App.xaml.cs index d974684..5b8552d 100644 --- a/Il2CppInspector.GUI/App.xaml.cs +++ b/Il2CppInspector.GUI/App.xaml.cs @@ -70,7 +70,15 @@ namespace Il2CppInspectorGUI public List AppModels { get; } = new List(); - public Exception LastException { get; private set; } + private Exception _lastException; + public Exception LastException { + get { + var ex = _lastException; + _lastException = null; + return ex; + } + private set => _lastException = value; + } // Event to indicate current work status public event EventHandler OnStatusUpdate; @@ -84,8 +92,11 @@ namespace Il2CppInspectorGUI // Set handlers for plugin manager PluginManager.ErrorHandler += (s, e) => { - if (e is PluginOptionsChangedEventInfo) - MessageBox.Show("Could not update plugin options. " + e.Error.Exception.Message, "Plugin error"); + if (e is PluginOptionsChangedEventInfo oe) + if (oe.Error is PluginOptionErrorEventArgs oea) + MessageBox.Show($"Plugin option '{oea.Option.Description}' for {e.Error.Plugin.Name} is invalid: {e.Error.Exception.Message}", "Plugin error"); + else + MessageBox.Show($"One or more plugin options for {e.Error.Plugin.Name} are invalid: {e.Error.Exception.Message}", "Plugin error"); else MessageBox.Show($"The plugin {e.Error.Plugin.Name} encountered an error while executing {e.Error.Operation}: {e.Error.Exception.Message}." + Environment.NewLine + Environment.NewLine + "Plugin has been disabled.", "Plugin error"); @@ -131,6 +142,10 @@ namespace Il2CppInspectorGUI public Task LoadMetadataAsync(MemoryStream metadataStream) => Task.Run(() => { try { + // Don't start unless every enabled plugin's options are valid + if (PluginManager.ValidateAllOptions().Error != null) + return false; + metadata = Metadata.FromStream(metadataStream, StatusUpdate); return true; } diff --git a/Il2CppInspector.GUI/MainWindow.xaml.cs b/Il2CppInspector.GUI/MainWindow.xaml.cs index a52ca96..fb629bf 100644 --- a/Il2CppInspector.GUI/MainWindow.xaml.cs +++ b/Il2CppInspector.GUI/MainWindow.xaml.cs @@ -121,7 +121,8 @@ namespace Il2CppInspectorGUI else { areaBusyIndicator.Visibility = Visibility.Hidden; grdFirstPage.Visibility = Visibility.Visible; - MessageBox.Show(this, app.LastException.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error); + if (app.LastException is Exception e) + MessageBox.Show(this, e.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error); } } @@ -157,7 +158,8 @@ namespace Il2CppInspectorGUI else { areaBusyIndicator.Visibility = Visibility.Hidden; btnSelectBinaryFile.Visibility = Visibility.Visible; - MessageBox.Show(this, app.LastException.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error); + if (app.LastException is Exception e) + MessageBox.Show(this, e.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error); } } @@ -195,7 +197,8 @@ namespace Il2CppInspectorGUI else { areaBusyIndicator.Visibility = Visibility.Hidden; grdFirstPage.Visibility = Visibility.Visible; - MessageBox.Show(this, app.LastException.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error); + if (app.LastException is Exception e) + MessageBox.Show(this, e.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error); } }