mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-09 12:46:47 +02:00
catch plugin init fails - stop Wox from not starting up and crushing and disable and explain the user what is the probalmatic plugin
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -92,21 +93,36 @@ namespace Wox.Core.Plugin
|
|||||||
Settings.UpdatePluginSettings(_metadatas);
|
Settings.UpdatePluginSettings(_metadatas);
|
||||||
AllPlugins = PluginsLoader.Plugins(_metadatas, Settings);
|
AllPlugins = PluginsLoader.Plugins(_metadatas, Settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call initialize for all plugins
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>return the list of failed to init plugins or null for none</returns>
|
||||||
public static void InitializePlugins(IPublicAPI api)
|
public static void InitializePlugins(IPublicAPI api)
|
||||||
{
|
{
|
||||||
API = api;
|
API = api;
|
||||||
|
var failedPlugins = new ConcurrentQueue<PluginPair>();
|
||||||
Parallel.ForEach(AllPlugins, pair =>
|
Parallel.ForEach(AllPlugins, pair =>
|
||||||
{
|
{
|
||||||
var milliseconds = Stopwatch.Debug($"|PluginManager.InitializePlugins|Init method time cost for <{pair.Metadata.Name}>", () =>
|
try
|
||||||
{
|
{
|
||||||
pair.Plugin.Init(new PluginInitContext
|
var milliseconds = Stopwatch.Debug($"|PluginManager.InitializePlugins|Init method time cost for <{pair.Metadata.Name}>", () =>
|
||||||
{
|
{
|
||||||
CurrentPluginMetadata = pair.Metadata,
|
pair.Plugin.Init(new PluginInitContext
|
||||||
API = API
|
{
|
||||||
|
CurrentPluginMetadata = pair.Metadata,
|
||||||
|
API = API
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
pair.Metadata.InitTime += milliseconds;
|
||||||
pair.Metadata.InitTime += milliseconds;
|
Log.Info($"|PluginManager.InitializePlugins|Total init cost for <{pair.Metadata.Name}> is <{pair.Metadata.InitTime}ms>");
|
||||||
Log.Info($"|PluginManager.InitializePlugins|Total init cost for <{pair.Metadata.Name}> is <{pair.Metadata.InitTime}ms>");
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.Exception(nameof(PluginManager), $"Fail to Init plugin: {pair.Metadata.Name}", e);
|
||||||
|
pair.Metadata.Disabled = true; // TODO: not sure this really disable it later on
|
||||||
|
failedPlugins.Enqueue(pair);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
_contextMenuPlugins = GetPluginsForInterface<IContextMenu>();
|
_contextMenuPlugins = GetPluginsForInterface<IContextMenu>();
|
||||||
@@ -121,6 +137,11 @@ namespace Wox.Core.Plugin
|
|||||||
.ForEach(x => NonGlobalPlugins[x] = plugin);
|
.ForEach(x => NonGlobalPlugins[x] = plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (failedPlugins.Any())
|
||||||
|
{
|
||||||
|
var failed = string.Join(",", failedPlugins.Select(x => x.Metadata.Name));
|
||||||
|
API.ShowMsg($"Fail to Init Plugins", $"Plugins: {failed} - fail to load and would be disabled, please contact plugin creator for help", "", false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void InstallPlugin(string path)
|
public static void InstallPlugin(string path)
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ namespace Wox.Infrastructure.Logger
|
|||||||
{
|
{
|
||||||
public const string DirectoryName = "Logs";
|
public const string DirectoryName = "Logs";
|
||||||
|
|
||||||
public static string CurrentLogDirectory { get; private set; }
|
public static string CurrentLogDirectory { get; }
|
||||||
|
|
||||||
static Log()
|
static Log()
|
||||||
{
|
{
|
||||||
@@ -53,6 +53,14 @@ namespace Wox.Infrastructure.Logger
|
|||||||
|
|
||||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||||
public static void Exception(string className, string message, System.Exception exception, [CallerMemberName] string methodName = "")
|
public static void Exception(string className, string message, System.Exception exception, [CallerMemberName] string methodName = "")
|
||||||
|
{
|
||||||
|
var classNameWithMethod = CheckClassAndMessageAndReturnFullClassWithMethod(className, message, methodName);
|
||||||
|
|
||||||
|
ExceptionInternal(classNameWithMethod, message, exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string CheckClassAndMessageAndReturnFullClassWithMethod(string className, string message,
|
||||||
|
string methodName)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(className))
|
if (string.IsNullOrWhiteSpace(className))
|
||||||
{
|
{
|
||||||
@@ -60,16 +68,17 @@ namespace Wox.Infrastructure.Logger
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(message))
|
if (string.IsNullOrWhiteSpace(message))
|
||||||
{ // todo: not sure we really need that
|
{
|
||||||
|
// todo: not sure we really need that
|
||||||
LogFaultyFormat($"Fail to specify a message during logging");
|
LogFaultyFormat($"Fail to specify a message during logging");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(methodName))
|
if (!string.IsNullOrWhiteSpace(methodName))
|
||||||
{
|
{
|
||||||
className += "." + methodName;
|
return className + "." + methodName;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExceptionInternal(className, message, exception);
|
return className;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ExceptionInternal(string classAndMethod, string message, System.Exception e)
|
private static void ExceptionInternal(string classAndMethod, string message, System.Exception e)
|
||||||
@@ -140,18 +149,48 @@ namespace Wox.Infrastructure.Logger
|
|||||||
LogInternal(message, LogLevel.Error);
|
LogInternal(message, LogLevel.Error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Error(string className, string message, [CallerMemberName] string methodName = "")
|
||||||
|
{
|
||||||
|
LogInternal(LogLevel.Error, className, message, methodName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void LogInternal(LogLevel level, string className, string message, [CallerMemberName] string methodName = "")
|
||||||
|
{
|
||||||
|
var classNameWithMethod = CheckClassAndMessageAndReturnFullClassWithMethod(className, message, methodName);
|
||||||
|
|
||||||
|
var logger = LogManager.GetLogger(classNameWithMethod);
|
||||||
|
|
||||||
|
System.Diagnostics.Debug.WriteLine($"{level.Name}|{message}");
|
||||||
|
logger.Log(level, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Debug(string className, string message, [CallerMemberName] string methodName = "")
|
||||||
|
{
|
||||||
|
LogInternal(LogLevel.Debug, className, message, methodName);
|
||||||
|
}
|
||||||
|
|
||||||
/// <param name="message">example: "|prefix|unprefixed" </param>
|
/// <param name="message">example: "|prefix|unprefixed" </param>
|
||||||
public static void Debug(string message)
|
public static void Debug(string message)
|
||||||
{
|
{
|
||||||
LogInternal(message, LogLevel.Debug);
|
LogInternal(message, LogLevel.Debug);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Info(string className, string message, [CallerMemberName] string methodName = "")
|
||||||
|
{
|
||||||
|
LogInternal(LogLevel.Info, className, message, methodName);
|
||||||
|
}
|
||||||
|
|
||||||
/// <param name="message">example: "|prefix|unprefixed" </param>
|
/// <param name="message">example: "|prefix|unprefixed" </param>
|
||||||
public static void Info(string message)
|
public static void Info(string message)
|
||||||
{
|
{
|
||||||
LogInternal(message, LogLevel.Info);
|
LogInternal(message, LogLevel.Info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Warn(string className, string message, [CallerMemberName] string methodName = "")
|
||||||
|
{
|
||||||
|
LogInternal(LogLevel.Warn, className, message, methodName);
|
||||||
|
}
|
||||||
|
|
||||||
/// <param name="message">example: "|prefix|unprefixed" </param>
|
/// <param name="message">example: "|prefix|unprefixed" </param>
|
||||||
public static void Warn(string message)
|
public static void Warn(string message)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ namespace Wox.Plugin
|
|||||||
/// <param name="title">Message title</param>
|
/// <param name="title">Message title</param>
|
||||||
/// <param name="subTitle">Message subtitle</param>
|
/// <param name="subTitle">Message subtitle</param>
|
||||||
/// <param name="iconPath">Message icon path (relative path to your plugin folder)</param>
|
/// <param name="iconPath">Message icon path (relative path to your plugin folder)</param>
|
||||||
void ShowMsg(string title, string subTitle = "", string iconPath = "");
|
void ShowMsg(string title, string subTitle = "", string iconPath = "", bool useMainWindowAsOwner = true);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Open setting dialog
|
/// Open setting dialog
|
||||||
|
|||||||
@@ -46,6 +46,9 @@ namespace Wox.Plugin
|
|||||||
[Obsolete("Use IcoPath")]
|
[Obsolete("Use IcoPath")]
|
||||||
public string FullIcoPath => IcoPath;
|
public string FullIcoPath => IcoPath;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Init time include both plugin load time and init time
|
||||||
|
/// </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public long InitTime { get; set; }
|
public long InitTime { get; set; }
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
|
|||||||
@@ -91,12 +91,12 @@ namespace Wox
|
|||||||
_mainVM.MainWindowVisibility = Visibility.Visible;
|
_mainVM.MainWindowVisibility = Visibility.Visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ShowMsg(string title, string subTitle = "", string iconPath = "")
|
public void ShowMsg(string title, string subTitle = "", string iconPath = "", bool useMainWindowAsOwner = true)
|
||||||
{
|
{
|
||||||
Application.Current.Dispatcher.Invoke(() =>
|
Application.Current.Dispatcher.Invoke(() =>
|
||||||
{
|
{
|
||||||
var m = new Msg { Owner = Application.Current.MainWindow };
|
var msg = useMainWindowAsOwner ? new Msg {Owner = Application.Current.MainWindow} : new Msg();
|
||||||
m.Show(title, subTitle, iconPath);
|
msg.Show(title, subTitle, iconPath);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user