Merge branch 'V1.2.0' of https://github.com/qianlifeng/Wox into V1.2.0

This commit is contained in:
qianlifeng 2014-12-31 12:43:02 +08:00
commit 96d908094b
54 changed files with 712 additions and 532 deletions

View file

@ -29,11 +29,13 @@ Name: english; MessagesFile: compiler:Default.isl
Type: files; Name: "{commonstartup}\{#MyAppName}.lnk"
[Tasks]
Name: desktopicon; Description: {cm:CreateDesktopIcon}; GroupDescription: {cm:AdditionalIcons}; Flags: unchecked
Name: desktopicon; Description: {cm:CreateDesktopIcon}; GroupDescription: {cm:AdditionalIcons};
Name: startupfolder; Description: Startup with Windows;
[Files]
Source: {#MyAppPath}\*; DestDir: {app}; Flags: ignoreversion recursesubdirs
Source: {#MyAppPath}\*; Excludes: Plugins\*,Themes\*; DestDir: {app}; Flags: ignoreversion recursesubdirs
Source: {#MyAppPath}\Plugins\*; DestDir: {%USERPROFILE}\.Wox\Plugins; Flags: ignoreversion recursesubdirs
Source: {#MyAppPath}\Themes\*; DestDir: {%USERPROFILE}\.Wox\Themes; Flags: ignoreversion recursesubdirs
[Icons]
Name: {group}\{#MyAppName}; Filename: {app}\{#MyAppExeName}
@ -42,4 +44,10 @@ Name: {userdesktop}\{#MyAppName}; Filename: {app}\{#MyAppExeName}; Tasks: deskto
Name: {userstartup}\{#MyAppName}; Filename: {app}\{#MyAppExeName}; Tasks: startupfolder
[Run]
Filename: {app}\{#MyAppExeName}; Description: {cm:LaunchProgram,{#MyAppName}}; Flags: nowait postinstall skipifsilent
Filename: {app}\{#MyAppExeName}; Description: {cm:LaunchProgram,{#MyAppName}}; Flags: nowait postinstall skipifsilent unchecked
[UninstallDelete]
Type: filesandordirs; Name: "{%USERPROFILE}\.Wox"
[UninstallRun]
Filename: {sys}\taskkill.exe; Parameters: "/f /im Wox.exe"; Flags: skipifdoesntexist runhidden

View file

@ -197,7 +197,7 @@ namespace Wox.Plugin.PluginManagement
private List<Result> ListUnInstalledPlugins(Query query)
{
List<Result> results = new List<Result>();
List<PluginMetadata> allInstalledPlugins = ParseThirdPartyPlugins();
List<PluginMetadata> allInstalledPlugins = ParseUserPlugins();
if (query.ActionParameters.Count > 1)
{
string pluginName = query.ActionParameters[1];
@ -235,7 +235,7 @@ namespace Wox.Plugin.PluginManagement
private List<Result> ListInstalledPlugins()
{
List<Result> results = new List<Result>();
foreach (PluginMetadata plugin in ParseThirdPartyPlugins())
foreach (PluginMetadata plugin in ParseUserPlugins())
{
results.Add(new Result()
{
@ -247,7 +247,7 @@ namespace Wox.Plugin.PluginManagement
return results;
}
private static List<PluginMetadata> ParseThirdPartyPlugins()
private static List<PluginMetadata> ParseUserPlugins()
{
List<PluginMetadata> pluginMetadatas = new List<PluginMetadata>();
if (!Directory.Exists(PluginPath))
@ -276,7 +276,7 @@ namespace Wox.Plugin.PluginManagement
try
{
metadata = JsonConvert.DeserializeObject<PluginMetadata>(File.ReadAllText(configPath));
metadata.PluginType = PluginType.ThirdParty;
metadata.PluginType = PluginType.User;
metadata.PluginDirectory = pluginDirectory;
}
catch (Exception)

View file

@ -0,0 +1,206 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Xml;
using Microsoft.Win32;
namespace Wox.Core.Exception
{
public class ExceptionFormatter
{
public static string FormatExcpetion(object exception)
{
return CreateExceptionReport(exception);
}
private static string CreateExceptionReport(object exceptionObject)
{
var sb = new StringBuilder();
sb.AppendLine("## Exception");
sb.AppendLine();
sb.AppendLine("```");
var ex = exceptionObject as System.Exception;
if (ex != null)
{
var exlist = new List<StringBuilder>();
while (ex != null)
{
var exsb = new StringBuilder();
exsb.Append(ex.GetType().FullName);
exsb.Append(": ");
exsb.AppendLine(ex.Message);
if (ex.Source != null)
{
exsb.Append(" Source: ");
exsb.AppendLine(ex.Source);
}
if (ex.TargetSite != null)
{
exsb.Append(" TargetAssembly: ");
exsb.AppendLine(ex.TargetSite.Module.Assembly.ToString());
exsb.Append(" TargetModule: ");
exsb.AppendLine(ex.TargetSite.Module.ToString());
exsb.Append(" TargetSite: ");
exsb.AppendLine(ex.TargetSite.ToString());
}
exsb.AppendLine(ex.StackTrace);
exlist.Add(exsb);
ex = ex.InnerException;
}
foreach (var result in exlist.Select(o => o.ToString()).Reverse())
{
sb.AppendLine(result);
}
sb.AppendLine("```");
sb.AppendLine();
}
else
{
sb.AppendLine(exceptionObject.GetType().FullName);
sb.AppendLine(new StackTrace().ToString());
sb.AppendLine("```");
sb.AppendLine();
}
sb.AppendLine("## Environment");
sb.AppendLine();
sb.Append("* Command Line: ");
sb.AppendLine(Environment.CommandLine);
sb.Append("* Timestamp: ");
sb.AppendLine(XmlConvert.ToString(DateTime.Now));
sb.Append("* IntPtr Length: ");
sb.AppendLine(IntPtr.Size.ToString());
sb.Append("* System Version: ");
sb.AppendLine(Environment.OSVersion.VersionString);
sb.Append("* CLR Version: ");
sb.AppendLine(Environment.Version.ToString());
sb.AppendLine("* Installed .NET Framework: ");
foreach (var result in GetFrameworkVersionFromRegistry())
{
sb.Append(" * ");
sb.AppendLine(result);
}
sb.AppendLine();
sb.AppendLine("## Assemblies - " + System.AppDomain.CurrentDomain.FriendlyName);
sb.AppendLine();
foreach (var ass in System.AppDomain.CurrentDomain.GetAssemblies().OrderBy(o => o.GlobalAssemblyCache ? 100 : 0))
{
sb.Append("* ");
sb.Append(ass.FullName);
sb.Append(" (");
sb.Append(string.IsNullOrEmpty(ass.Location) ? "not supported" : ass.Location);
sb.AppendLine(")");
}
var process = System.Diagnostics.Process.GetCurrentProcess();
sb.AppendLine();
sb.AppendLine("## Modules - " + process.ProcessName);
sb.AppendLine();
foreach (ProcessModule mod in process.Modules)
{
sb.Append("* ");
sb.Append(mod.FileName);
sb.Append(" (");
sb.Append(mod.FileVersionInfo.FileDescription);
sb.Append(", ");
sb.Append(mod.FileVersionInfo.FileVersion);
sb.Append(", ");
sb.Append(mod.FileVersionInfo.ProductName);
sb.Append(", ");
sb.Append(mod.FileVersionInfo.ProductVersion);
sb.Append(", ");
sb.Append(mod.FileVersionInfo.CompanyName);
sb.Append("), ");
sb.Append(string.Format("0x{0:X16}", mod.BaseAddress.ToInt64()));
sb.AppendLine();
}
sb.AppendLine();
sb.AppendLine("## Threads - " + process.Threads.Count);
sb.AppendLine();
foreach (ProcessThread th in process.Threads)
{
sb.Append("* ");
sb.AppendLine(string.Format("{0}, {1} {2}, Started: {3}, StartAddress: 0x{4:X16}", th.Id, th.ThreadState, th.PriorityLevel, th.StartTime, th.StartAddress.ToInt64()));
}
return sb.ToString();
}
// http://msdn.microsoft.com/en-us/library/hh925568%28v=vs.110%29.aspx
private static List<string> GetFrameworkVersionFromRegistry()
{
try
{
var result = new List<string>();
using (RegistryKey ndpKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\NET Framework Setup\NDP\"))
{
foreach (string versionKeyName in ndpKey.GetSubKeyNames())
{
if (versionKeyName.StartsWith("v"))
{
RegistryKey versionKey = ndpKey.OpenSubKey(versionKeyName);
string name = (string)versionKey.GetValue("Version", "");
string sp = versionKey.GetValue("SP", "").ToString();
string install = versionKey.GetValue("Install", "").ToString();
if (install != "")
if (sp != "" && install == "1")
result.Add(string.Format("{0} {1} SP{2}", versionKeyName, name, sp));
else
result.Add(string.Format("{0} {1}", versionKeyName, name));
if (name != "")
{
continue;
}
foreach (string subKeyName in versionKey.GetSubKeyNames())
{
RegistryKey subKey = versionKey.OpenSubKey(subKeyName);
name = (string)subKey.GetValue("Version", "");
if (name != "")
sp = subKey.GetValue("SP", "").ToString();
install = subKey.GetValue("Install", "").ToString();
if (install != "")
{
if (sp != "" && install == "1")
result.Add(string.Format("{0} {1} {2} SP{3}", versionKeyName, subKeyName, name, sp));
else if (install == "1")
result.Add(string.Format("{0} {1} {2}", versionKeyName, subKeyName, name));
}
}
}
}
}
using (RegistryKey ndpKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\"))
{
int releaseKey = (int)ndpKey.GetValue("Release");
{
if (releaseKey == 378389)
result.Add("v4.5");
if (releaseKey == 378675)
result.Add("v4.5.1 installed with Windows 8.1");
if (releaseKey == 378758)
result.Add("4.5.1 installed on Windows 8, Windows 7 SP1, or Windows Vista SP2");
}
}
return result;
}
catch (System.Exception e)
{
return new List<string>();
}
}
}
}

View file

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Wox.Core.Exception
{
/// <summary>
/// Represent exceptions that wox can't handle and MUST close running Wox.
/// </summary>
public class WoxCritialException : WoxException
{
public WoxCritialException(string msg) : base(msg)
{
}
}
}

View file

@ -0,0 +1,14 @@
namespace Wox.Core.Exception
{
/// <summary>
/// Base Wox Exceptions
/// </summary>
public class WoxException : System.Exception
{
public WoxException(string msg)
: base(msg)
{
}
}
}

View file

@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Wox.Infrastructure.Exceptions
namespace Wox.Core.Exception
{
public class WoxHttpException :WoxException
{

View file

@ -1,4 +1,4 @@
namespace Wox.Infrastructure.Exceptions
namespace Wox.Core.Exception
{
public class WoxJsonRPCException : WoxException
{

View file

@ -44,7 +44,7 @@ namespace Wox.Core.Plugin
plugins.Add(pair);
}
}
catch (Exception e)
catch (System.Exception e)
{
Log.Error(string.Format("Couldn't load plugin {0}: {1}", metadata.Name, e.Message));
#if (DEBUG)

View file

@ -4,8 +4,8 @@ using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Windows.Forms;
using Newtonsoft.Json;
using Wox.Infrastructure.Exceptions;
using Wox.Infrastructure.Logger;
using Wox.Plugin;
@ -72,9 +72,8 @@ namespace Wox.Core.Plugin
}
return results;
}
catch (Exception e)
catch (System.Exception e)
{
ErrorReporting.TryShowErrorMessageBox(e.Message, e);
Log.Error(e.Message);
}
}
@ -83,14 +82,14 @@ namespace Wox.Core.Plugin
private void ExecuteWoxAPI(string method, object[] parameters)
{
MethodInfo methodInfo = App.Window.GetType().GetMethod(method);
if (methodInfo != null)
MethodInfo methodInfo = PluginManager.API.GetType().GetMethod(method);
if (methodInfo != null)
{
try
{
methodInfo.Invoke(App.Window, parameters);
methodInfo.Invoke(PluginManager.API, parameters);
}
catch (Exception)
catch (System.Exception)
{
#if (DEBUG)
{
@ -132,7 +131,7 @@ namespace Wox.Core.Plugin
string result = reader.ReadToEnd();
if (result.StartsWith("DEBUG:"))
{
System.Windows.Forms.MessageBox.Show(new Form { TopMost = true }, result.Substring(6));
MessageBox.Show(new Form { TopMost = true }, result.Substring(6));
return "";
}
if (string.IsNullOrEmpty(result))
@ -142,7 +141,8 @@ namespace Wox.Core.Plugin
string error = errorReader.ReadToEnd();
if (!string.IsNullOrEmpty(error))
{
ErrorReporting.TryShowErrorMessageBox(error, new WoxJsonRPCException(error));
//todo:
// ErrorReporting.TryShowErrorMessageBox(error, new WoxJsonRPCException(error));
}
}
}

View file

@ -13,7 +13,7 @@ namespace Wox.Core.Plugin
return jsonRPCPluginMetadatas.Select(metadata => new PluginPair()
{
Plugin = jsonRPCPlugin,
Plugin = new T(), //every JsonRPC plugin should has its own plugin instance
Metadata = metadata
}).ToList();
}

View file

@ -4,7 +4,7 @@ using System.IO;
using System.Linq;
using System.Reflection;
using Newtonsoft.Json;
using Wox.Infrastructure.Exceptions;
using Wox.Core.Exception;
using Wox.Infrastructure.Logger;
using Wox.Infrastructure.Storage.UserSettings;
using Wox.Plugin;
@ -28,7 +28,7 @@ namespace Wox.Core.Plugin
ParseSystemPlugins();
foreach (string pluginDirectory in pluginDirectories)
{
ParseThirdPartyPlugins(pluginDirectory);
ParseUserPlugins(pluginDirectory);
}
if (PluginManager.DebuggerMode != null)
@ -41,6 +41,13 @@ namespace Wox.Core.Plugin
private static void ParseSystemPlugins()
{
string systemPluginPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
"Wox.Plugin.SystemPlugins.dll");
if (!File.Exists(systemPluginPath))
{
throw new WoxCritialException("System Plugin DLL is missing.");
}
pluginMetadatas.Add(new PluginMetadata()
{
Name = "System Plugins",
@ -56,16 +63,24 @@ namespace Wox.Core.Plugin
});
}
private static void ParseThirdPartyPlugins(string pluginDirectory)
private static void ParseUserPlugins(string pluginDirectory)
{
if (!Directory.Exists(pluginDirectory)) return;
string[] directories = Directory.GetDirectories(pluginDirectory);
foreach (string directory in directories)
{
if (File.Exists((Path.Combine(directory, "NeedDelete.txt"))))
{
Directory.Delete(directory, true);
continue;
try
{
Directory.Delete(directory, true);
continue;
}
catch (System.Exception e)
{
Log.Error(ExceptionFormatter.FormatExcpetion(e));
}
}
PluginMetadata metadata = GetPluginMetadata(directory);
if (metadata != null)
@ -88,10 +103,10 @@ namespace Wox.Core.Plugin
try
{
metadata = JsonConvert.DeserializeObject<PluginMetadata>(File.ReadAllText(configPath));
metadata.PluginType = PluginType.ThirdParty;
metadata.PluginType = PluginType.User;
metadata.PluginDirectory = pluginDirectory;
}
catch (Exception)
catch (System.Exception)
{
string error = string.Format("Parse plugin config {0} failed: json format is not valid", configPath);
Log.Warn(error);
@ -138,4 +153,4 @@ namespace Wox.Core.Plugin
return metadata;
}
}
}
}

View file

@ -1,18 +1,17 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Forms;
using ICSharpCode.SharpZipLib.Zip;
using Newtonsoft.Json;
using Wox.Core.Plugin;
using Wox.Plugin;
namespace Wox.Helper
namespace Wox.Core.Plugin
{
public class PluginInstaller
internal class PluginInstaller
{
public static void Install(string path)
internal static void Install(string path)
{
if (File.Exists(path))
{
@ -37,11 +36,7 @@ namespace Wox.Helper
return;
}
string pluginFolerPath = Path.Combine(Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath), "Plugins");
if (!Directory.Exists(pluginFolerPath))
{
Directory.CreateDirectory(pluginFolerPath);
}
string pluginFolerPath = PluginManager.DefaultPluginDirectory;
string newPluginName = plugin.Name
.Replace("/", "_")
@ -66,9 +61,9 @@ namespace Wox.Helper
plugin.Name, existingPlugin.Metadata.Version, plugin.Version, plugin.Author);
}
MessageBoxResult result = MessageBox.Show(content, "Install plugin",
MessageBoxButton.YesNo, MessageBoxImage.Question);
if (result == MessageBoxResult.Yes)
DialogResult result = MessageBox.Show(content, "Install plugin", MessageBoxButtons.YesNo,
MessageBoxIcon.Question);
if (result == DialogResult.Yes)
{
if (existingPlugin != null && Directory.Exists(existingPlugin.Metadata.PluginDirectory))
{
@ -88,7 +83,7 @@ namespace Wox.Helper
// Plugins.Init();
//}
if (MessageBox.Show("You have installed plugin " + plugin.Name + " successfully.\r\n Restart Wox to take effect?", "Install plugin",
MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
{
ProcessStartInfo Info = new ProcessStartInfo();
Info.Arguments = "/C ping 127.0.0.1 -n 1 && \"" +
@ -97,7 +92,7 @@ namespace Wox.Helper
Info.CreateNoWindow = true;
Info.FileName = "cmd.exe";
Process.Start(Info);
App.Window.CloseApp();
PluginManager.API.CloseApp();
}
}
}
@ -116,15 +111,15 @@ namespace Wox.Helper
try
{
metadata = JsonConvert.DeserializeObject<PluginMetadata>(File.ReadAllText(configPath));
metadata.PluginType = PluginType.ThirdParty;
metadata.PluginType = PluginType.User;
metadata.PluginDirectory = pluginDirectory;
}
catch (Exception)
catch (System.Exception)
{
string error = string.Format("Parse plugin config {0} failed: json format is not valid", configPath);
#if (DEBUG)
{
throw new Exception(error);
throw new System.Exception(error);
}
#endif
return null;
@ -137,7 +132,7 @@ namespace Wox.Helper
metadata.Language);
#if (DEBUG)
{
throw new Exception(error);
throw new System.Exception(error);
}
#endif
return null;
@ -148,7 +143,7 @@ namespace Wox.Helper
metadata.ExecuteFilePath);
#if (DEBUG)
{
throw new Exception(error);
throw new System.Exception(error);
}
#endif
return null;

View file

@ -4,7 +4,9 @@ using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
using Wox.Core.Exception;
using Wox.Infrastructure.Http;
using Wox.Infrastructure.Logger;
using Wox.Plugin;
namespace Wox.Core.Plugin
@ -15,21 +17,43 @@ namespace Wox.Core.Plugin
public static class PluginManager
{
public static String DebuggerMode { get; private set; }
public static IPublicAPI API { get; private set; }
private static List<PluginPair> plugins = new List<PluginPair>();
/// <summary>
/// Directories that will hold Wox plugin directory
/// </summary>
private static List<string> pluginDirectories = new List<string>();
static PluginManager()
/// <summary>
/// Default plugin directory
/// new plugin will be installed to this directory
/// </summary>
public static string DefaultPluginDirectory
{
get
{
string userProfilePath = Environment.GetEnvironmentVariable("USERPROFILE");
if (string.IsNullOrEmpty(userProfilePath))
{
throw new WoxCritialException("Wox Can't Find Environment Variable UserProfile");
}
return Path.Combine(Path.Combine(userProfilePath, ".Wox"), "Plugins");
}
}
private static void SetupPluginDirectories()
{
pluginDirectories.Clear();
pluginDirectories.Add(DefaultPluginDirectory);
pluginDirectories.Add(
Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Plugins"));
pluginDirectories.Add(
Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), ".Wox"),"Plugins"));
MakesurePluginDirectoriesExist();
MakesurePluginDirectoriesExist();
}
private static void MakesurePluginDirectoriesExist()
@ -38,7 +62,14 @@ namespace Wox.Core.Plugin
{
if (!Directory.Exists(pluginDirectory))
{
Directory.CreateDirectory(pluginDirectory);
try
{
Directory.CreateDirectory(pluginDirectory);
}
catch (System.Exception e)
{
Log.Error(e.Message);
}
}
}
}
@ -46,8 +77,12 @@ namespace Wox.Core.Plugin
/// <summary>
/// Load and init all Wox plugins
/// </summary>
public static void Init()
public static void Init(IPublicAPI api)
{
if (api == null) throw new WoxCritialException("api is null");
SetupPluginDirectories();
API = api;
plugins.Clear();
List<PluginMetadata> pluginMetadatas = PluginConfig.Parse(pluginDirectories);
@ -61,11 +96,21 @@ namespace Wox.Core.Plugin
{
CurrentPluginMetadata = pair.Metadata,
Proxy = HttpProxy.Instance,
API = App.Window
API = API
}));
}
}
public static void InstallPlugin(string path)
{
PluginInstaller.Install(path);
}
public static void Query(Query query)
{
QueryDispatcher.QueryDispatcher.Dispatch(query);
}
public static List<PluginPair> AllPlugins
{
get
@ -74,11 +119,11 @@ namespace Wox.Core.Plugin
}
}
public static bool HitThirdpartyKeyword(Query query)
public static bool IsUserPluginQuery(Query query)
{
if (string.IsNullOrEmpty(query.ActionName)) return false;
return plugins.Any(o => o.Metadata.PluginType == PluginType.ThirdParty && o.Metadata.ActionKeyword == query.ActionName);
return plugins.Any(o => o.Metadata.PluginType == PluginType.User && o.Metadata.ActionKeyword == query.ActionName);
}
public static void ActivatePluginDebugger(string path)

View file

@ -0,0 +1,7 @@
namespace Wox.Core.Plugin.QueryDispatcher
{
internal interface IQueryDispatcher
{
void Dispatch(Wox.Plugin.Query query);
}
}

View file

@ -0,0 +1,21 @@

namespace Wox.Core.Plugin.QueryDispatcher
{
internal static class QueryDispatcher
{
private static IQueryDispatcher pluginCmd = new UserPluginQueryDispatcher();
private static IQueryDispatcher systemCmd = new SystemPluginQueryDispatcher();
public static void Dispatch(Wox.Plugin.Query query)
{
if (PluginManager.IsUserPluginQuery(query))
{
pluginCmd.Dispatch(query);
}
else
{
systemCmd.Dispatch(query);
}
}
}
}

View file

@ -1,20 +1,17 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using Wox.Core.Plugin;
using Wox.Infrastructure.Storage.UserSettings;
using Wox.Plugin;
using Wox.Plugin.SystemPlugins;
namespace Wox.Commands
namespace Wox.Core.Plugin.QueryDispatcher
{
public class SystemCommand : BaseCommand
public class SystemPluginQueryDispatcher : IQueryDispatcher
{
private IEnumerable<PluginPair> allSytemPlugins = PluginManager.AllPlugins.Where(o => o.Metadata.PluginType == PluginType.System);
public override void Dispatch(Query query)
public void Dispatch(Query query)
{
var queryPlugins = allSytemPlugins;
if (UserSettingStorage.Instance.WebSearches.Exists(o => o.ActionWord == query.ActionName && o.Enabled))
@ -22,7 +19,7 @@ namespace Wox.Commands
//websearch mode
queryPlugins = new List<PluginPair>()
{
allSytemPlugins.First(o => ((ISystemPlugin)o.Plugin).ID == "565B73353DBF4806919830B9202EE3BF")
allSytemPlugins.First(o => o.Metadata.ID == "565B73353DBF4806919830B9202EE3BF")
};
}
@ -34,7 +31,7 @@ namespace Wox.Commands
List<Result> results = pair1.Plugin.Query(query);
results.ForEach(o => { o.AutoAjustScore = true; });
App.Window.PushResults(query, pair1.Metadata, results);
PluginManager.API.PushResults(query, pair1.Metadata, results);
});
}
}

View file

@ -2,26 +2,24 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Wox.Core.Plugin;
using Wox.Helper;
using Wox.Infrastructure.Logger;
using Wox.Infrastructure.Storage.UserSettings;
using Wox.Plugin;
namespace Wox.Commands
namespace Wox.Core.Plugin.QueryDispatcher
{
public class PluginCommand : BaseCommand
public class UserPluginQueryDispatcher : IQueryDispatcher
{
public override void Dispatch(Query query)
public void Dispatch(Query query)
{
PluginPair thirdPlugin = PluginManager.AllPlugins.FirstOrDefault(o => o.Metadata.ActionKeyword == query.ActionName);
if (thirdPlugin != null && !string.IsNullOrEmpty(thirdPlugin.Metadata.ActionKeyword))
PluginPair userPlugin = PluginManager.AllPlugins.FirstOrDefault(o => o.Metadata.ActionKeyword == query.ActionName);
if (userPlugin != null && !string.IsNullOrEmpty(userPlugin.Metadata.ActionKeyword))
{
var customizedPluginConfig = UserSettingStorage.Instance.CustomizedPluginConfigs.FirstOrDefault(o => o.ID == thirdPlugin.Metadata.ID);
var customizedPluginConfig = UserSettingStorage.Instance.CustomizedPluginConfigs.FirstOrDefault(o => o.ID == userPlugin.Metadata.ID);
if (customizedPluginConfig != null && customizedPluginConfig.Disabled)
{
//need to stop the loading animation
UpdateResultView(null);
PluginManager.API.StopLoadingBar();
return;
}
@ -29,12 +27,12 @@ namespace Wox.Commands
{
try
{
List<Result> results = thirdPlugin.Plugin.Query(query) ?? new List<Result>();
App.Window.PushResults(query,thirdPlugin.Metadata,results);
List<Result> results = userPlugin.Plugin.Query(query) ?? new List<Result>();
PluginManager.API.PushResults(query,userPlugin.Metadata,results);
}
catch (Exception queryException)
catch (System.Exception queryException)
{
Log.Error(string.Format("Plugin {0} query failed: {1}", thirdPlugin.Metadata.Name,
Log.Error(string.Format("Plugin {0} query failed: {1}", userPlugin.Metadata.Name,
queryException.Message));
#if (DEBUG)
{

5
Wox.Core/README.md Normal file
View file

@ -0,0 +1,5 @@
What does Wox.Core do?
=====
* Handle Query
* Loading Plugins (including system plugin and user plugin)

View file

@ -1,4 +0,0 @@
What does Wox.Core do?
* Handle Query
* Loading Plugins

View file

@ -18,7 +18,7 @@
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<OutputPath>..\Output\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
@ -32,18 +32,33 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Newtonsoft.Json.6.0.7\lib\net35\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Exception\ExceptionFormatter.cs" />
<Compile Include="Exception\WoxCritialException.cs" />
<Compile Include="Exception\WoxException.cs" />
<Compile Include="Exception\WoxHttpException.cs" />
<Compile Include="Exception\WoxJsonRPCException.cs" />
<Compile Include="Plugin\PluginInstaller.cs" />
<Compile Include="Plugin\QueryDispatcher\IQueryDispatcher.cs" />
<Compile Include="Plugin\QueryDispatcher\QueryDispatcher.cs" />
<Compile Include="Plugin\QueryDispatcher\UserPluginQueryDispatcher.cs" />
<Compile Include="Plugin\QueryDispatcher\SystemPluginQueryDispatcher.cs" />
<Compile Include="Plugin\JsonRPCPlugin.cs" />
<Compile Include="Plugin\JsonRPCPluginLoader.cs" />
<Compile Include="Plugin\CSharpPluginLoader.cs" />
@ -55,7 +70,7 @@
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="README.txt" />
<None Include="README.md" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Wox.Infrastructure\Wox.Infrastructure.csproj">

View file

@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Newtonsoft.Json" version="6.0.7" targetFramework="net35" />
<package id="SharpZipLib" version="0.86.0" targetFramework="net35" />
</packages>

View file

@ -1,15 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Wox.Infrastructure
{
public static class ChineseToPinYin
{
[Obsolete]
public static string ToPinYin(string txt)
{
return txt.Unidecode();
}
}
}

View file

@ -1,13 +0,0 @@
using System;
namespace Wox.Infrastructure.Exceptions
{
public class WoxException : Exception
{
public WoxException(string msg)
: base(msg)
{
}
}
}

View file

@ -1,4 +1,5 @@
using System.Reflection;
using System;
using System.Reflection;
using log4net;
namespace Wox.Infrastructure.Logger

View file

@ -10,18 +10,35 @@ using Newtonsoft.Json;
namespace Wox.Infrastructure.Storage
{
[Serializable]
public abstract class BaseStorage<T> : IStorage where T : class,IStorage,new()
public abstract class BaseStorage<T> : IStorage where T : class,IStorage, new()
{
private readonly string configFolder = Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), "Config");
private string configFolder;
private string ConfigFolder
{
get
{
if (string.IsNullOrEmpty(configFolder))
{
string userProfilePath = Environment.GetEnvironmentVariable("USERPROFILE");
if (userProfilePath == null)
{
throw new ArgumentException("Environment variable USERPROFILE is empty");
}
configFolder = Path.Combine(Path.Combine(userProfilePath, ".Wox"), "Config");
}
return configFolder;
}
}
protected string ConfigPath
{
get
{
return Path.Combine(configFolder, ConfigName + FileSuffix);
return Path.Combine(ConfigFolder, ConfigName + FileSuffix);
}
}
protected abstract string FileSuffix { get; }
protected abstract string ConfigName { get; }
@ -72,9 +89,9 @@ namespace Wox.Infrastructure.Storage
{
if (!File.Exists(ConfigPath))
{
if (!Directory.Exists(configFolder))
if (!Directory.Exists(ConfigFolder))
{
Directory.CreateDirectory(configFolder);
Directory.CreateDirectory(ConfigFolder);
}
File.Create(ConfigPath).Close();
}

View file

@ -174,7 +174,15 @@ namespace Wox.Infrastructure.Storage.UserSettings
if (string.IsNullOrEmpty(storage.ProgramSuffixes))
{
storage.ProgramSuffixes = "lnk;exe;appref-ms;bat";
}
}
if (storage.QueryBoxFont == null)
{
storage.QueryBoxFont = FontFamily.GenericSansSerif.Name;
}
if (storage.ResultItemFont == null)
{
storage.ResultItemFont = FontFamily.GenericSansSerif.Name;
}
}
}

View file

@ -56,9 +56,6 @@
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
<Compile Include="Exceptions\WoxException.cs" />
<Compile Include="Exceptions\WoxHttpException.cs" />
<Compile Include="Exceptions\WoxJsonRPCException.cs" />
<Compile Include="Http\HttpProxy.cs" />
<Compile Include="Logger\Log.cs" />
<Compile Include="PeHeaderReader.cs" />
@ -67,21 +64,18 @@
<Compile Include="Storage\JsonStrorage.cs" />
<Compile Include="Storage\UserSettings\CustomizedPluginConfig.cs" />
<Compile Include="Storage\UserSettings\FolderLink.cs" />
<Compile Include="Storage\UserSettings\PluginHotkey.cs" />
<Compile Include="Storage\UserSettings\ProgramSource.cs" />
<Compile Include="Storage\UserSettings\UserSettingStorage.cs" />
<Compile Include="Storage\UserSettings\WebSearch.cs" />
<Compile Include="Timeit.cs" />
<Compile Include="Unidecoder.Characters.cs" />
<Compile Include="ChineseToPinYin.cs" />
<Compile Include="Http\HttpRequest.cs" />
<Compile Include="Storage\BaseStorage.cs" />
<Compile Include="FuzzyMatcher.cs" />
<Compile Include="Hotkey\GlobalHotkey.cs" />
<Compile Include="Hotkey\HotkeyModel.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Storage\UserSelectedRecordStorage.cs" />
<Compile Include="Storage\UserSettings\UserSettingStorage.cs" />
<Compile Include="Storage\UserSettings\PluginHotkey.cs" />
<Compile Include="Storage\UserSettings\ProgramSource.cs" />
<Compile Include="Storage\UserSettings\WebSearch.cs" />
<Compile Include="StringEmptyConverter.cs" />
<Compile Include="Unidecoder.cs" />
<Compile Include="WindowsShellRun.cs" />
</ItemGroup>

View file

@ -22,4 +22,4 @@ namespace Wox.Plugin.SystemPlugins.ControlPanel
GUID = newGUID;
}
}
}
}

View file

@ -4,6 +4,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:infrastructure="clr-namespace:Wox.Infrastructure;assembly=Wox.Infrastructure"
xmlns:program="clr-namespace:Wox.Plugin.SystemPlugins.Program"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="600">
@ -26,7 +27,7 @@
<GridViewColumn Header="Location" Width="400">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Location, ConverterParameter=(null), Converter={infrastructure:StringEmptyConverter}}"/>
<TextBlock Text="{Binding Location, ConverterParameter=(null), Converter={program:StringEmptyConverter}}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>

View file

@ -1,11 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Data;
using System.Windows.Markup;
namespace Wox.Infrastructure
namespace Wox.Plugin.SystemPlugins.Program
{
public class StringEmptyConverter : MarkupExtension, IValueConverter
{

View file

@ -8,7 +8,7 @@ using Wox.Infrastructure.Storage.UserSettings;
namespace Wox.Plugin.SystemPlugins
{
public class ThirdpartyPluginIndicator : BaseSystemPlugin
public class UserPluginIndicator : BaseSystemPlugin
{
private List<PluginPair> allPlugins = new List<PluginPair>();
private PluginInitContext context;

View file

@ -86,6 +86,7 @@
<Compile Include="Program\ProgramSuffixes.xaml.cs">
<DependentUpon>ProgramSuffixes.xaml</DependentUpon>
</Compile>
<Compile Include="Program\StringEmptyConverter.cs" />
<Compile Include="SuggestionSources\Baidu.cs" />
<Compile Include="SuggestionSources\SuggestionSourceFactory.cs" />
<Compile Include="Sys\SysSettings.xaml.cs">
@ -102,7 +103,7 @@
<Compile Include="Program\Programs.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Sys\Sys.cs" />
<Compile Include="ThirdpartyPluginIndicator.cs" />
<Compile Include="UserPluginIndicator.cs" />
<Compile Include="SuggestionSources\Google.cs" />
<Compile Include="SuggestionSources\ISuggestionSource.cs" />
<Compile Include="WebSearch\WebSearchSetting.xaml.cs">

View file

@ -6,7 +6,12 @@ namespace Wox.Plugin
{
public interface IPublicAPI
{
/// <summary>
/// Push result to query window
/// </summary>
/// <param name="query"></param>
/// <param name="plugin"></param>
/// <param name="results"></param>
void PushResults(Query query,PluginMetadata plugin, List<Result> results);
bool ShellRun(string cmd, bool runAsAdministrator = false);

View file

@ -8,6 +8,6 @@ namespace Wox.Plugin
public enum PluginType
{
System,
ThirdParty
User
}
}
}

5
Wox.Plugin/README.md Normal file
View file

@ -0,0 +1,5 @@
What does Wox.Plugin do?
====
* Define base objects and interfaces for plugins
* Plugin Author who making C# plugin should reference this DLL via nuget

View file

@ -59,6 +59,9 @@
<Compile Include="Result.cs" />
<Compile Include="ActionContext.cs" />
</ItemGroup>
<ItemGroup>
<None Include="README.md" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.

View file

@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Moq;
using NUnit.Framework;
using Wox.Core.Exception;
using Wox.Core.Plugin;
using Wox.Plugin;
namespace Wox.Test.Plugins
{
[TestFixture]
public class PluginInitTest
{
[Test]
public void CouldNotFindUserProfileTest()
{
var api = new Mock<IPublicAPI>();
Environment.SetEnvironmentVariable("USERPROFILE", "");
Assert.Throws(typeof(WoxCritialException), () => PluginManager.Init(api.Object));
}
[Test]
public void PublicAPIIsNullTest()
{
Assert.Throws(typeof(WoxCritialException), () => PluginManager.Init(null));
}
}
}

View file

@ -32,6 +32,9 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Moq">
<HintPath>..\packages\Moq.4.2.1409.1722\lib\net35\Moq.dll</HintPath>
</Reference>
<Reference Include="nunit.framework">
<HintPath>..\packages\NUnit.2.6.3\lib\nunit.framework.dll</HintPath>
</Reference>
@ -44,6 +47,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="FuzzyMatcherTest.cs" />
<Compile Include="Plugins\PluginInitTest.cs" />
<Compile Include="QueryTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="UrlPluginTest.cs" />
@ -52,6 +56,10 @@
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Wox.Core\Wox.Core.csproj">
<Project>{B749F0DB-8E75-47DB-9E5E-265D16D0C0D2}</Project>
<Name>Wox.Core</Name>
</ProjectReference>
<ProjectReference Include="..\Wox.Infrastructure\Wox.Infrastructure.csproj">
<Project>{4FD29318-A8AB-4D8F-AA47-60BC241B8DA3}</Project>
<Name>Wox.Infrastructure</Name>

View file

@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Moq" version="4.2.1409.1722" targetFramework="net35" />
<package id="NUnit" version="2.6.3" targetFramework="net35" />
</packages>

View file

@ -8,7 +8,13 @@
</appSettings>
<log4net>
<appender name="LogFileAppender" type="log4net.Appender.FileAppender">
<file value="log.txt"/>
<file type="log4net.Util.PatternString">
<converter>
<name value="WoxLogPathConverter" />
<type value="Wox.Helper.WoxLogPathConverter,Wox" />
</converter>
<conversionPattern value="%WoxLogPathConverter{log}\\log.txt" />
</file>
<appendToFile value="true"/>
<rollingStyle value="Date"/>
<datePattern value="yyyyMMdd-HH:mm:ss"/>

View file

@ -4,6 +4,7 @@ using System.IO;
using System.Linq;
using System.Text;
using System.Windows;
using Wox.Core.Plugin;
using Wox.Helper;
namespace Wox.CommandArgs
@ -25,7 +26,7 @@ namespace Wox.CommandArgs
MessageBox.Show("Plugin " + path + " didn't exist");
return;
}
PluginInstaller.Install(path);
PluginManager.InstallPlugin(path);
}
}
}

View file

@ -15,7 +15,7 @@ namespace Wox.CommandArgs
public void Execute(IList<string> args)
{
PluginManager.Init();
PluginManager.Init(App.Window);
}
}
}

View file

@ -1,18 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Wox.Plugin;
namespace Wox.Commands
{
public abstract class BaseCommand
{
public abstract void Dispatch(Query query);
protected void UpdateResultView(List<Result> results)
{
App.Window.OnUpdateResultView(results);
}
}
}

View file

@ -1,28 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Wox.Core.Plugin;
using Wox.Helper;
using Wox.Plugin;
namespace Wox.Commands
{
internal static class CommandFactory
{
private static PluginCommand pluginCmd = new PluginCommand();
private static SystemCommand systemCmd = new SystemCommand();
public static void DispatchCommand(Query query)
{
if (PluginManager.HitThirdpartyKeyword(query))
{
pluginCmd.Dispatch(query);
}
else
{
systemCmd.Dispatch(query);
}
}
}
}

View file

@ -1,38 +0,0 @@
using System;
using System.ComponentModel;
using System.Threading;
using System.Windows.Data;
using System.Windows.Threading;
namespace Wox.Converters
{
public class AsyncTask : INotifyPropertyChanged
{
public AsyncTask(Func<object> valueFunc)
{
LoadValue(valueFunc);
}
private void LoadValue(Func<object> valueFunc)
{
var frame = new DispatcherFrame();
ThreadPool.QueueUserWorkItem(delegate
{
object returnValue =
AsyncValue = valueFunc();
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("AsyncValue"));
});
}
public event PropertyChangedEventHandler PropertyChanged;
public object AsyncValue
{
get;
set;
}
}
}

View file

@ -8,6 +8,7 @@ using System.Windows.Forms;
using System.Windows.Threading;
using System.Xml;
using Microsoft.Win32;
using Wox.Core.Exception;
using Wox.Infrastructure.Logger;
namespace Wox.Helper.ErrorReporting
@ -16,10 +17,9 @@ namespace Wox.Helper.ErrorReporting
{
public static void UnhandledExceptionHandle(object sender, System.UnhandledExceptionEventArgs e)
{
if (System.Diagnostics.Debugger.IsAttached) return;
string error = CreateExceptionReport("System.AppDomain.UnhandledException", e.ExceptionObject);
if (Debugger.IsAttached) return;
string error = ExceptionFormatter.FormatExcpetion(e.ExceptionObject);
//e.IsTerminating is always true in most times, so try to avoid use this property
//http://stackoverflow.com/questions/10982443/what-causes-the-unhandledexceptioneventargs-isterminating-flag-to-be-true-or-fal
Log.Error(error);
@ -31,211 +31,22 @@ namespace Wox.Helper.ErrorReporting
if (Debugger.IsAttached) return;
e.Handled = true;
string error = CreateExceptionReport("System.Windows.Application.DispatcherUnhandledException", e.Exception);
string error = ExceptionFormatter.FormatExcpetion(e.Exception);
Log.Error(error);
TryShowErrorMessageBox(error, e.Exception);
}
public static void ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
{
if (Debugger.IsAttached) return;
string error = CreateExceptionReport("System.Windows.Forms.Application.ThreadException", e.Exception);
string error = ExceptionFormatter.FormatExcpetion(e.Exception);
Log.Fatal(error);
TryShowErrorMessageBox(error, e.Exception);
}
private static string CreateExceptionReport(string ev, object exceptionObject)
{
var sb = new StringBuilder();
sb.AppendLine("## Exception");
sb.AppendLine();
sb.AppendLine("```");
var ex = exceptionObject as Exception;
if (ex != null)
{
var exlist = new List<StringBuilder>();
while (ex != null)
{
var exsb = new StringBuilder();
exsb.Append(ex.GetType().FullName);
exsb.Append(": ");
exsb.AppendLine(ex.Message);
if (ex.Source != null)
{
exsb.Append(" Source: ");
exsb.AppendLine(ex.Source);
}
if (ex.TargetSite != null)
{
exsb.Append(" TargetAssembly: ");
exsb.AppendLine(ex.TargetSite.Module.Assembly.ToString());
exsb.Append(" TargetModule: ");
exsb.AppendLine(ex.TargetSite.Module.ToString());
exsb.Append(" TargetSite: ");
exsb.AppendLine(ex.TargetSite.ToString());
}
exsb.AppendLine(ex.StackTrace);
exlist.Add(exsb);
ex = ex.InnerException;
}
foreach (var result in exlist.Select(o => o.ToString()).Reverse())
{
sb.AppendLine(result);
}
sb.AppendLine("```");
sb.AppendLine();
}
else
{
sb.AppendLine(exceptionObject.GetType().FullName);
sb.AppendLine(new StackTrace().ToString());
sb.AppendLine("```");
sb.AppendLine();
}
sb.AppendLine("## Environment");
sb.AppendLine();
sb.Append("* Command Line: ");
sb.AppendLine(Environment.CommandLine);
sb.Append("* Exception Handle: ");
sb.AppendLine(ev);
sb.Append("* Timestamp: ");
sb.AppendLine(XmlConvert.ToString(DateTime.Now));
sb.Append("* IntPtr Length: ");
sb.AppendLine(IntPtr.Size.ToString());
sb.Append("* System Version: ");
sb.AppendLine(Environment.OSVersion.VersionString);
sb.Append("* CLR Version: ");
sb.AppendLine(Environment.Version.ToString());
sb.AppendLine("* Installed .NET Framework: ");
foreach (var result in GetFrameworkVersionFromRegistry())
{
sb.Append(" * ");
sb.AppendLine(result);
}
sb.AppendLine();
sb.AppendLine("## Assemblies - " + System.AppDomain.CurrentDomain.FriendlyName);
sb.AppendLine();
foreach (var ass in System.AppDomain.CurrentDomain.GetAssemblies().OrderBy(o => o.GlobalAssemblyCache ? 100 : 0))
{
sb.Append("* ");
sb.Append(ass.FullName);
sb.Append(" (");
sb.Append(SyntaxSugars.CallOrRescueDefault(() => ass.Location, "not supported"));
sb.AppendLine(")");
}
var process = System.Diagnostics.Process.GetCurrentProcess();
sb.AppendLine();
sb.AppendLine("## Modules - " + process.ProcessName);
sb.AppendLine();
foreach (ProcessModule mod in process.Modules)
{
sb.Append("* ");
sb.Append(mod.FileName);
sb.Append(" (");
sb.Append(mod.FileVersionInfo.FileDescription);
sb.Append(", ");
sb.Append(mod.FileVersionInfo.FileVersion);
sb.Append(", ");
sb.Append(mod.FileVersionInfo.ProductName);
sb.Append(", ");
sb.Append(mod.FileVersionInfo.ProductVersion);
sb.Append(", ");
sb.Append(mod.FileVersionInfo.CompanyName);
sb.Append("), ");
sb.Append(string.Format("0x{0:X16}", mod.BaseAddress.ToInt64()));
sb.AppendLine();
}
sb.AppendLine();
sb.AppendLine("## Threads - " + process.Threads.Count);
sb.AppendLine();
foreach (ProcessThread th in process.Threads)
{
sb.Append("* ");
sb.AppendLine(string.Format("{0}, {1} {2}, Started: {3}, StartAddress: 0x{4:X16}", th.Id, th.ThreadState, th.PriorityLevel, th.StartTime, th.StartAddress.ToInt64()));
}
return sb.ToString();
}
// http://msdn.microsoft.com/en-us/library/hh925568%28v=vs.110%29.aspx
private static List<string> GetFrameworkVersionFromRegistry()
{
try
{
var result = new List<string>();
using (RegistryKey ndpKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\NET Framework Setup\NDP\"))
{
foreach (string versionKeyName in ndpKey.GetSubKeyNames())
{
if (versionKeyName.StartsWith("v"))
{
RegistryKey versionKey = ndpKey.OpenSubKey(versionKeyName);
string name = (string)versionKey.GetValue("Version", "");
string sp = versionKey.GetValue("SP", "").ToString();
string install = versionKey.GetValue("Install", "").ToString();
if (install != "")
if (sp != "" && install == "1")
result.Add(string.Format("{0} {1} SP{2}", versionKeyName, name, sp));
else
result.Add(string.Format("{0} {1}", versionKeyName, name));
if (name != "")
{
continue;
}
foreach (string subKeyName in versionKey.GetSubKeyNames())
{
RegistryKey subKey = versionKey.OpenSubKey(subKeyName);
name = (string)subKey.GetValue("Version", "");
if (name != "")
sp = subKey.GetValue("SP", "").ToString();
install = subKey.GetValue("Install", "").ToString();
if (install != "")
{
if (sp != "" && install == "1")
result.Add(string.Format("{0} {1} {2} SP{3}", versionKeyName, subKeyName, name, sp));
else if (install == "1")
result.Add(string.Format("{0} {1} {2}", versionKeyName, subKeyName, name));
}
}
}
}
}
using (RegistryKey ndpKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\"))
{
int releaseKey = (int)ndpKey.GetValue("Release");
{
if (releaseKey == 378389)
result.Add("v4.5");
if (releaseKey == 378675)
result.Add("v4.5.1 installed with Windows 8.1");
if (releaseKey == 378758)
result.Add("4.5.1 installed on Windows 8, Windows 7 SP1, or Windows Vista SP2");
}
}
return result;
}
catch (Exception e)
{
return new List<string>();
}
}
public static bool TryShowErrorMessageBox(string error, object exceptionObject)
{
var title = "Wox - Unhandled Exception";
@ -271,11 +82,13 @@ namespace Wox.Helper.ErrorReporting
var dialog = new WPFErrorReportingDialog(error, title, exceptionObject);
dialog.ShowDialog();
}
private static void ShowWPFMessageBox(string error, string title)
{
System.Windows.MessageBox.Show(error, title, MessageBoxButton.OK, MessageBoxImage.Error,
MessageBoxResult.OK, System.Windows.MessageBoxOptions.None);
}
private static void ShowWindowsFormsMessageBox(string error, string title)
{
System.Windows.Forms.MessageBox.Show(error, title, MessageBoxButtons.OK,

View file

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace Wox.Helper
{
public class WoxLogPathConverter : log4net.Util.PatternConverter
{
protected override void Convert(TextWriter writer, object state)
{
string userProfilePath = Environment.GetEnvironmentVariable("USERPROFILE");
writer.Write(Path.Combine(userProfilePath, ".Wox"));
}
}
}

View file

@ -9,8 +9,8 @@ namespace Wox.ImageLoader
[Serializable]
public class ImageCacheStroage : BinaryStorage<ImageCacheStroage>
{
public int counter = 0;
public const int maxCached = 200;
private int counter = 0;
private const int maxCached = 200;
public Dictionary<string, int> TopUsedImages = new Dictionary<string, int>();
protected override string ConfigName

View file

@ -13,7 +13,6 @@ namespace Wox.ImageLoader
public class ImageLoader
{
private static readonly Dictionary<string, ImageSource> imageCache = new Dictionary<string, ImageSource>();
private static object locker = new object();
private static readonly List<string> imageExts = new List<string>
{
@ -54,23 +53,20 @@ namespace Wox.ImageLoader
{
//ImageCacheStroage.Instance.TopUsedImages can be changed during foreach, so we need to make a copy
var imageList = new Dictionary<string, int>(ImageCacheStroage.Instance.TopUsedImages);
using (new Timeit(string.Format("Preload {0} images",imageList.Count)))
using (new Timeit(string.Format("Preload {0} images", imageList.Count)))
{
foreach (var image in imageList)
{
ImageSource img = Load(image.Key, false);
if (img != null)
if (!imageCache.ContainsKey(image.Key))
{
img.Freeze(); //to make it copy to UI thread
if (!imageCache.ContainsKey(image.Key))
ImageSource img = Load(image.Key, false);
if (img != null)
{
lock (locker)
img.Freeze(); //to make it copy to UI thread
if (!imageCache.ContainsKey(image.Key))
{
if (!imageCache.ContainsKey(image.Key))
{
KeyValuePair<string, int> copyedImg = image;
App.Window.Dispatcher.Invoke(new Action(() => imageCache.Add(copyedImg.Key, img)));
}
KeyValuePair<string, int> copyedImg = image;
App.Window.Dispatcher.Invoke(new Action(() => imageCache.Add(copyedImg.Key, img)));
}
}
}
@ -78,7 +74,7 @@ namespace Wox.ImageLoader
}
}
public static ImageSource Load(string path,bool addToCache = true)
public static ImageSource Load(string path, bool addToCache = true)
{
if (string.IsNullOrEmpty(path)) return null;
if (addToCache)
@ -112,13 +108,7 @@ namespace Wox.ImageLoader
{
if (!imageCache.ContainsKey(path))
{
lock (locker)
{
if (!imageCache.ContainsKey(path))
{
imageCache.Add(path, img);
}
}
imageCache.Add(path, img);
}
}

View file

@ -14,7 +14,6 @@ using WindowsInput;
using WindowsInput.Native;
using NHotkey;
using NHotkey.Wpf;
using Wox.Commands;
using Wox.Core.Plugin;
using Wox.Helper;
using Wox.Infrastructure;
@ -22,6 +21,7 @@ using Wox.Infrastructure.Hotkey;
using Wox.Infrastructure.Storage;
using Wox.Infrastructure.Storage.UserSettings;
using Wox.Plugin;
using Wox.Storage;
using Wox.Update;
using Application = System.Windows.Application;
using Brushes = System.Windows.Media.Brushes;
@ -37,6 +37,7 @@ using Path = System.IO.Path;
using Rectangle = System.Drawing.Rectangle;
using TextBox = System.Windows.Controls.TextBox;
using ToolTip = System.Windows.Controls.ToolTip;
using Wox.Infrastructure.Logger;
namespace Wox
{
@ -122,12 +123,12 @@ namespace Wox
public void InstallPlugin(string path)
{
Dispatcher.Invoke(new Action(() => PluginInstaller.Install(path)));
Dispatcher.Invoke(new Action(() => PluginManager.InstallPlugin(path)));
}
public void ReloadPlugins()
{
Dispatcher.Invoke(new Action(PluginManager.Init));
Dispatcher.Invoke(new Action(()=> PluginManager.Init(this)));
}
public List<PluginPair> GetAllPlugins()
@ -172,14 +173,8 @@ namespace Wox
pnlResult.RightMouseClickEvent += pnlResult_RightMouseClickEvent;
ThreadPool.SetMaxThreads(30, 10);
try
{
SetTheme(UserSettingStorage.Instance.Theme);
}
catch (Exception)
{
SetTheme(UserSettingStorage.Instance.Theme = "Dark");
}
ThemeManager.ChangeTheme(UserSettingStorage.Instance.Theme);
SetHotkey(UserSettingStorage.Instance.Hotkey, OnHotkey);
SetCustomPluginHotkey();
@ -192,7 +187,7 @@ namespace Wox
ThreadPool.QueueUserWorkItem(o =>
{
Thread.Sleep(50);
PluginManager.Init();
PluginManager.Init(this);
});
ThreadPool.QueueUserWorkItem(o =>
{
@ -357,9 +352,9 @@ namespace Wox
}, TimeSpan.FromMilliseconds(100), null);
queryHasReturn = false;
var q = new Query(lastQuery);
CommandFactory.DispatchCommand(q);
PluginManager.Query(q);
BackToResultMode();
if (PluginManager.HitThirdpartyKeyword(q))
if (PluginManager.IsUserPluginQuery(q))
{
Dispatcher.DelayInvoke("ShowProgressbar", originQuery =>
{
@ -676,44 +671,6 @@ namespace Wox
}
}
public void SetTheme(string themeName)
{
var dict = new ResourceDictionary
{
Source = new Uri(Path.Combine(Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath), "Themes\\" + themeName + ".xaml"), UriKind.Absolute)
};
Style queryBoxStyle = dict["QueryBoxStyle"] as Style;
if (queryBoxStyle != null)
{
queryBoxStyle.Setters.Add(new Setter(TextBox.FontFamilyProperty, new FontFamily(UserSettingStorage.Instance.QueryBoxFont)));
queryBoxStyle.Setters.Add(new Setter(TextBox.FontStyleProperty, FontHelper.GetFontStyleFromInvariantStringOrNormal(UserSettingStorage.Instance.QueryBoxFontStyle)));
queryBoxStyle.Setters.Add(new Setter(TextBox.FontWeightProperty, FontHelper.GetFontWeightFromInvariantStringOrNormal(UserSettingStorage.Instance.QueryBoxFontWeight)));
queryBoxStyle.Setters.Add(new Setter(TextBox.FontStretchProperty, FontHelper.GetFontStretchFromInvariantStringOrNormal(UserSettingStorage.Instance.QueryBoxFontStretch)));
}
Style resultItemStyle = dict["ItemTitleStyle"] as Style;
Style resultSubItemStyle = dict["ItemSubTitleStyle"] as Style;
Style resultItemSelectedStyle = dict["ItemTitleSelectedStyle"] as Style;
Style resultSubItemSelectedStyle = dict["ItemSubTitleSelectedStyle"] as Style;
if (resultItemStyle != null && resultSubItemStyle != null && resultSubItemSelectedStyle != null && resultItemSelectedStyle != null)
{
Setter fontFamily = new Setter(TextBlock.FontFamilyProperty, new FontFamily(UserSettingStorage.Instance.ResultItemFont));
Setter fontStyle = new Setter(TextBlock.FontStyleProperty, FontHelper.GetFontStyleFromInvariantStringOrNormal(UserSettingStorage.Instance.ResultItemFontStyle));
Setter fontWeight = new Setter(TextBlock.FontWeightProperty, FontHelper.GetFontWeightFromInvariantStringOrNormal(UserSettingStorage.Instance.ResultItemFontWeight));
Setter fontStretch = new Setter(TextBlock.FontStretchProperty, FontHelper.GetFontStretchFromInvariantStringOrNormal(UserSettingStorage.Instance.ResultItemFontStretch));
Setter[] setters = new Setter[] { fontFamily, fontStyle, fontWeight, fontStretch };
Array.ForEach(new Style[] { resultItemStyle, resultSubItemStyle, resultItemSelectedStyle, resultSubItemSelectedStyle }, o => Array.ForEach(setters, p => o.Setters.Add(p)));
}
Application.Current.Resources.MergedDictionaries.Clear();
Application.Current.Resources.MergedDictionaries.Add(dict);
this.Opacity = this.AllowsTransparency ? UserSettingStorage.Instance.Opacity : 1;
}
public bool ShellRun(string cmd, bool runAsAdministrator = false)
{
try
@ -739,7 +696,7 @@ namespace Wox
string[] files = (string[])e.Data.GetData(System.Windows.DataFormats.FileDrop);
if (files[0].ToLower().EndsWith(".wox"))
{
PluginInstaller.Install(files[0]);
PluginManager.InstallPlugin(files[0]);
}
else
{

View file

@ -172,8 +172,7 @@ namespace Wox
}
//PreviewPanel
App.Window.SetTheme(UserSettingStorage.Instance.Theme);
ThemeManager.ChangeTheme(UserSettingStorage.Instance.Theme);
#endregion
#region Plugin
@ -195,7 +194,7 @@ namespace Wox
new CollectionContainer
{
Collection =
PluginManager.AllPlugins.Where(o => o.Metadata.PluginType == PluginType.ThirdParty)
PluginManager.AllPlugins.Where(o => o.Metadata.PluginType == PluginType.User)
}
};
lbPlugins.ItemsSource = plugins;
@ -366,7 +365,7 @@ namespace Wox
private void ThemeComboBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
string themeName = themeComboBox.SelectedItem.ToString();
MainWindow.SetTheme(themeName);
ThemeManager.ChangeTheme(themeName);
UserSettingStorage.Instance.Theme = themeName;
UserSettingStorage.Instance.Save();
}
@ -379,7 +378,7 @@ namespace Wox
this.cbQueryBoxFontFaces.SelectedItem = ((FontFamily)cbQueryBoxFont.SelectedItem).ChooseRegularFamilyTypeface();
UserSettingStorage.Instance.Save();
App.Window.SetTheme(UserSettingStorage.Instance.Theme);
ThemeManager.ChangeTheme(UserSettingStorage.Instance.Theme);
}
private void CbQueryBoxFontFaces_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
@ -399,7 +398,7 @@ namespace Wox
UserSettingStorage.Instance.QueryBoxFontWeight = typeface.Weight.ToString();
UserSettingStorage.Instance.QueryBoxFontStyle = typeface.Style.ToString();
UserSettingStorage.Instance.Save();
App.Window.SetTheme(UserSettingStorage.Instance.Theme);
ThemeManager.ChangeTheme(UserSettingStorage.Instance.Theme);
}
}
@ -411,7 +410,7 @@ namespace Wox
this.cbResultItemFontFaces.SelectedItem = ((FontFamily)cbResultItemFont.SelectedItem).ChooseRegularFamilyTypeface();
UserSettingStorage.Instance.Save();
App.Window.SetTheme(UserSettingStorage.Instance.Theme);
ThemeManager.ChangeTheme(UserSettingStorage.Instance.Theme);
}
private void CbResultItemFontFaces_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
@ -422,8 +421,6 @@ namespace Wox
{
if (cbResultItemFontFaces.Items.Count > 0)
cbResultItemFontFaces.SelectedIndex = 0;
return;
}
else
{
@ -431,7 +428,7 @@ namespace Wox
UserSettingStorage.Instance.ResultItemFontWeight = typeface.Weight.ToString();
UserSettingStorage.Instance.ResultItemFontStyle = typeface.Style.ToString();
UserSettingStorage.Instance.Save();
App.Window.SetTheme(UserSettingStorage.Instance.Theme);
ThemeManager.ChangeTheme(UserSettingStorage.Instance.Theme);
}
}
@ -445,7 +442,7 @@ namespace Wox
else
PreviewMainPanel.Opacity = 1;
App.Window.SetTheme(UserSettingStorage.Instance.Theme);
ThemeManager.ChangeTheme(UserSettingStorage.Instance.Theme);
}
#endregion

View file

@ -1,12 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Generic;
using Newtonsoft.Json;
using Wox.Infrastructure.Storage;
using Wox.Plugin;
namespace Wox.Infrastructure.Storage
namespace Wox.Storage
{
public class UserSelectedRecordStorage : JsonStrorage<UserSelectedRecordStorage>
{

111
Wox/ThemeManager.cs Normal file
View file

@ -0,0 +1,111 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using Wox.Helper;
using Wox.Infrastructure.Logger;
using Wox.Infrastructure.Storage.UserSettings;
namespace Wox
{
internal class ThemeManager
{
private static List<string> themeDirectories = new List<string>();
static ThemeManager()
{
themeDirectories.Add(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Themes"));
string userProfilePath = Environment.GetEnvironmentVariable("USERPROFILE");
if (userProfilePath != null)
{
themeDirectories.Add(Path.Combine(Path.Combine(userProfilePath, ".Wox"), "Themes"));
}
MakesureThemeDirectoriesExist();
}
private static void MakesureThemeDirectoriesExist()
{
foreach (string pluginDirectory in themeDirectories)
{
if (!Directory.Exists(pluginDirectory))
{
try
{
Directory.CreateDirectory(pluginDirectory);
}
catch(Exception e)
{
Log.Error(e.Message);
}
}
}
}
public static void ChangeTheme(string themeName)
{
string themePath = GetThemePath(themeName);
if (string.IsNullOrEmpty(themePath))
{
themePath = GetThemePath("Dark");
if (string.IsNullOrEmpty(themePath))
{
throw new Exception("Change theme failed");
}
}
var dict = new ResourceDictionary
{
Source = new Uri(themePath, UriKind.Absolute)
};
Style queryBoxStyle = dict["QueryBoxStyle"] as Style;
if (queryBoxStyle != null)
{
queryBoxStyle.Setters.Add(new Setter(TextBox.FontFamilyProperty, new FontFamily(UserSettingStorage.Instance.QueryBoxFont)));
queryBoxStyle.Setters.Add(new Setter(TextBox.FontStyleProperty, FontHelper.GetFontStyleFromInvariantStringOrNormal(UserSettingStorage.Instance.QueryBoxFontStyle)));
queryBoxStyle.Setters.Add(new Setter(TextBox.FontWeightProperty, FontHelper.GetFontWeightFromInvariantStringOrNormal(UserSettingStorage.Instance.QueryBoxFontWeight)));
queryBoxStyle.Setters.Add(new Setter(TextBox.FontStretchProperty, FontHelper.GetFontStretchFromInvariantStringOrNormal(UserSettingStorage.Instance.QueryBoxFontStretch)));
}
Style resultItemStyle = dict["ItemTitleStyle"] as Style;
Style resultSubItemStyle = dict["ItemSubTitleStyle"] as Style;
Style resultItemSelectedStyle = dict["ItemTitleSelectedStyle"] as Style;
Style resultSubItemSelectedStyle = dict["ItemSubTitleSelectedStyle"] as Style;
if (resultItemStyle != null && resultSubItemStyle != null && resultSubItemSelectedStyle != null && resultItemSelectedStyle != null)
{
Setter fontFamily = new Setter(TextBlock.FontFamilyProperty, new FontFamily(UserSettingStorage.Instance.ResultItemFont));
Setter fontStyle = new Setter(TextBlock.FontStyleProperty, FontHelper.GetFontStyleFromInvariantStringOrNormal(UserSettingStorage.Instance.ResultItemFontStyle));
Setter fontWeight = new Setter(TextBlock.FontWeightProperty, FontHelper.GetFontWeightFromInvariantStringOrNormal(UserSettingStorage.Instance.ResultItemFontWeight));
Setter fontStretch = new Setter(TextBlock.FontStretchProperty, FontHelper.GetFontStretchFromInvariantStringOrNormal(UserSettingStorage.Instance.ResultItemFontStretch));
Setter[] setters = new Setter[] { fontFamily, fontStyle, fontWeight, fontStretch };
Array.ForEach(new Style[] { resultItemStyle, resultSubItemStyle, resultItemSelectedStyle, resultSubItemSelectedStyle }, o => Array.ForEach(setters, p => o.Setters.Add(p)));
}
Application.Current.Resources.MergedDictionaries.Clear();
Application.Current.Resources.MergedDictionaries.Add(dict);
}
private static string GetThemePath(string themeName)
{
foreach (string themeDirectory in themeDirectories)
{
string path = Path.Combine(themeDirectory, themeName + ".xaml");
if (File.Exists(path))
{
return path;
}
}
return string.Empty;
}
}
}

View file

@ -104,7 +104,10 @@
<Reference Include="WPFToolkit, Version=3.5.40128.1, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
</ItemGroup>
<ItemGroup>
<Compile Include="Helper\WoxLogPathConverter.cs" />
<Compile Include="ImageLoader\ImageCacheStroage.cs" />
<Compile Include="Storage\UserSelectedRecordStorage.cs" />
<Compile Include="ThemeManager.cs" />
<Compile Include="Update\NewVersionWindow.xaml.cs">
<DependentUpon>NewVersionWindow.xaml</DependentUpon>
</Compile>
@ -124,11 +127,6 @@
<Compile Include="CommandArgs\PluginDebuggerCommandArg.cs" />
<Compile Include="CommandArgs\QueryCommandArg.cs" />
<Compile Include="CommandArgs\ReloadPluginCommandArg.cs" />
<Compile Include="Commands\BaseCommand.cs" />
<Compile Include="Commands\CommandFactory.cs" />
<Compile Include="Commands\PluginCommand.cs" />
<Compile Include="Commands\SystemCommand.cs" />
<Compile Include="Converters\AsyncConverter.cs" />
<Compile Include="Converters\ConvertorBase.cs" />
<Compile Include="Helper\DataWebRequestFactory.cs" />
<Compile Include="Helper\ErrorReporting\ErrorReporting.cs" />
@ -148,7 +146,6 @@
</Compile>
<Compile Include="Helper\DispatcherExtensions.cs" />
<Compile Include="Helper\DWMDropShadow.cs" />
<Compile Include="Helper\PluginInstaller.cs" />
<Compile Include="HotkeyControl.xaml.cs">
<DependentUpon>HotkeyControl.xaml</DependentUpon>
</Compile>
@ -205,11 +202,6 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<None Include="Themes\Dark.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Themes\Light.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
@ -230,6 +222,10 @@
<SubType>Designer</SubType>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<Page Include="Themes\Dark.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Update\NewVersionWindow.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>