From 422e19724ab21eef2822eb85758d63d52b6863c9 Mon Sep 17 00:00:00 2001 From: qianlifeng Date: Sat, 21 Dec 2013 01:20:17 +0800 Subject: [PATCH] add IronPython environment to execute python plugins --- Plugins/WinAlfred.Plugin.DouBan/main.py | 4 + Plugins/WinAlfred.Plugin.DouBan/plugin.ini | 8 + .../EverythingAPI.cs | 335 ++++++++++++++---- Plugins/WinAlfred.Plugin.Everything/Main.cs | 15 +- .../WinAlfred.Plugin.Everything.csproj | 19 + .../WinAlfred.Plugin.Everything/plugin.ini | 8 + WinAlfred.Plugin/IPlugin.cs | 1 - WinAlfred.Plugin/Plugin.cs | 13 + WinAlfred.Plugin/PluginMetadata.cs | 2 + WinAlfred.Plugin/WinAlfred.Plugin.csproj | 20 ++ WinAlfred.sln | 14 + WinAlfred/FrmMain.Designer.cs | 14 +- WinAlfred/FrmMain.cs | 30 +- WinAlfred/Helper/Log.cs | 4 +- WinAlfred/PluginLoader/BasePluginLoader.cs | 26 +- WinAlfred/PluginLoader/CSharpPluginLoader.cs | 46 ++- WinAlfred/PluginLoader/PythonPluginLoader.cs | 21 +- WinAlfred/PluginLoader/PythonPluginWrapper.cs | 61 ++++ WinAlfred/WinAlfred.csproj | 44 ++- WinAlfred/packages.config | 1 + 20 files changed, 578 insertions(+), 108 deletions(-) create mode 100644 Plugins/WinAlfred.Plugin.DouBan/main.py create mode 100644 Plugins/WinAlfred.Plugin.DouBan/plugin.ini create mode 100644 Plugins/WinAlfred.Plugin.Everything/plugin.ini create mode 100644 WinAlfred.Plugin/Plugin.cs create mode 100644 WinAlfred/PluginLoader/PythonPluginWrapper.cs diff --git a/Plugins/WinAlfred.Plugin.DouBan/main.py b/Plugins/WinAlfred.Plugin.DouBan/main.py new file mode 100644 index 0000000000..94bd01fd36 --- /dev/null +++ b/Plugins/WinAlfred.Plugin.DouBan/main.py @@ -0,0 +1,4 @@ +import os + + + diff --git a/Plugins/WinAlfred.Plugin.DouBan/plugin.ini b/Plugins/WinAlfred.Plugin.DouBan/plugin.ini new file mode 100644 index 0000000000..c0105b8d19 --- /dev/null +++ b/Plugins/WinAlfred.Plugin.DouBan/plugin.ini @@ -0,0 +1,8 @@ +[plugin] +ActionKeyword = movie +Name = douban +Author = qianlifeng +Version = 0.1 +Language = python +Description = test +ExecuteFile = main.py diff --git a/Plugins/WinAlfred.Plugin.Everything/EverythingAPI.cs b/Plugins/WinAlfred.Plugin.Everything/EverythingAPI.cs index 524030dc7b..481a4ca53c 100644 --- a/Plugins/WinAlfred.Plugin.Everything/EverythingAPI.cs +++ b/Plugins/WinAlfred.Plugin.Everything/EverythingAPI.cs @@ -8,91 +8,274 @@ namespace WinAlfred.Plugin.Everything { public sealed class EverythingAPI { - const int EVERYTHING_OK = 0; - const int EVERYTHING_ERROR_MEMORY = 1; - const int EVERYTHING_ERROR_IPC = 2; - const int EVERYTHING_ERROR_REGISTERCLASSEX = 3; - const int EVERYTHING_ERROR_CREATEWINDOW = 4; - const int EVERYTHING_ERROR_CREATETHREAD = 5; - const int EVERYTHING_ERROR_INVALIDINDEX = 6; - const int EVERYTHING_ERROR_INVALIDCALL = 7; + #region Const + const string EVERYTHING_DLL_NAME = "Everything.dll"; + #endregion - [DllImport("Everything.dll")] - private static extern int Everything_SetSearch(string lpSearchString); - [DllImport("Everything.dll")] - private static extern void Everything_SetMatchPath(bool bEnable); - [DllImport("Everything.dll")] - private static extern void Everything_SetMatchCase(bool bEnable); - [DllImport("Everything.dll")] - private static extern void Everything_SetMatchWholeWord(bool bEnable); - [DllImport("Everything.dll")] - private static extern void Everything_SetRegex(bool bEnable); - [DllImport("Everything.dll")] - private static extern void Everything_SetMax(int dwMax); - [DllImport("Everything.dll")] - private static extern void Everything_SetOffset(int dwOffset); + #region DllImport + [DllImport(EVERYTHING_DLL_NAME)] + private static extern int Everything_SetSearch(string lpSearchString); + [DllImport(EVERYTHING_DLL_NAME)] + private static extern void Everything_SetMatchPath(bool bEnable); + [DllImport(EVERYTHING_DLL_NAME)] + private static extern void Everything_SetMatchCase(bool bEnable); + [DllImport(EVERYTHING_DLL_NAME)] + private static extern void Everything_SetMatchWholeWord(bool bEnable); + [DllImport(EVERYTHING_DLL_NAME)] + private static extern void Everything_SetRegex(bool bEnable); + [DllImport(EVERYTHING_DLL_NAME)] + private static extern void Everything_SetMax(int dwMax); + [DllImport(EVERYTHING_DLL_NAME)] + private static extern void Everything_SetOffset(int dwOffset); - [DllImport("Everything.dll")] - private static extern bool Everything_GetMatchPath(); - [DllImport("Everything.dll")] - private static extern bool Everything_GetMatchCase(); - [DllImport("Everything.dll")] - private static extern bool Everything_GetMatchWholeWord(); - [DllImport("Everything.dll")] - private static extern bool Everything_GetRegex(); - [DllImport("Everything.dll")] - private static extern UInt32 Everything_GetMax(); - [DllImport("Everything.dll")] - private static extern UInt32 Everything_GetOffset(); - [DllImport("Everything.dll")] - private static extern string Everything_GetSearch(); - [DllImport("Everything.dll")] - private static extern int Everything_GetLastError(); + [DllImport(EVERYTHING_DLL_NAME)] + private static extern bool Everything_GetMatchPath(); + [DllImport(EVERYTHING_DLL_NAME)] + private static extern bool Everything_GetMatchCase(); + [DllImport(EVERYTHING_DLL_NAME)] + private static extern bool Everything_GetMatchWholeWord(); + [DllImport(EVERYTHING_DLL_NAME)] + private static extern bool Everything_GetRegex(); + [DllImport(EVERYTHING_DLL_NAME)] + private static extern UInt32 Everything_GetMax(); + [DllImport(EVERYTHING_DLL_NAME)] + private static extern UInt32 Everything_GetOffset(); + [DllImport(EVERYTHING_DLL_NAME)] + private static extern string Everything_GetSearch(); + [DllImport(EVERYTHING_DLL_NAME)] + private static extern StateCode Everything_GetLastError(); - [DllImport("Everything.dll")] - private static extern bool Everything_Query(); + [DllImport(EVERYTHING_DLL_NAME)] + private static extern bool Everything_Query(); - [DllImport("Everything.dll")] - private static extern void Everything_SortResultsByPath(); + [DllImport(EVERYTHING_DLL_NAME)] + private static extern void Everything_SortResultsByPath(); - [DllImport("Everything.dll")] - private static extern int Everything_GetNumFileResults(); - [DllImport("Everything.dll")] - private static extern int Everything_GetNumFolderResults(); - [DllImport("Everything.dll")] - private static extern int Everything_GetNumResults(); - [DllImport("Everything.dll")] - private static extern int Everything_GetTotFileResults(); - [DllImport("Everything.dll")] - private static extern int Everything_GetTotFolderResults(); - [DllImport("Everything.dll")] - private static extern int Everything_GetTotResults(); - [DllImport("Everything.dll")] - private static extern bool Everything_IsVolumeResult(int nIndex); - [DllImport("Everything.dll")] - private static extern bool Everything_IsFolderResult(int nIndex); - [DllImport("Everything.dll")] - private static extern bool Everything_IsFileResult(int nIndex); - [DllImport("Everything.dll")] - private static extern void Everything_GetResultFullPathName(int nIndex, StringBuilder lpString, int nMaxCount); - [DllImport("Everything.dll")] - private static extern void Everything_Reset(); + [DllImport(EVERYTHING_DLL_NAME)] + private static extern int Everything_GetNumFileResults(); + [DllImport(EVERYTHING_DLL_NAME)] + private static extern int Everything_GetNumFolderResults(); + [DllImport(EVERYTHING_DLL_NAME)] + private static extern int Everything_GetNumResults(); + [DllImport(EVERYTHING_DLL_NAME)] + private static extern int Everything_GetTotFileResults(); + [DllImport(EVERYTHING_DLL_NAME)] + private static extern int Everything_GetTotFolderResults(); + [DllImport(EVERYTHING_DLL_NAME)] + private static extern int Everything_GetTotResults(); + [DllImport(EVERYTHING_DLL_NAME)] + private static extern bool Everything_IsVolumeResult(int nIndex); + [DllImport(EVERYTHING_DLL_NAME)] + private static extern bool Everything_IsFolderResult(int nIndex); + [DllImport(EVERYTHING_DLL_NAME)] + private static extern bool Everything_IsFileResult(int nIndex); + [DllImport(EVERYTHING_DLL_NAME)] + private static extern void Everything_GetResultFullPathName(int nIndex, StringBuilder lpString, int nMaxCount); + [DllImport(EVERYTHING_DLL_NAME)] + private static extern void Everything_Reset(); + #endregion + #region Enum + enum StateCode + { + OK, + MemoryError, + IPCError, + RegisterClassExError, + CreateWindowError, + CreateThreadError, + InvalidIndexError, + InvalidCallError + } + #endregion - public void Search(string query) - { - int i; - const int bufsize = 260; - StringBuilder buf = new StringBuilder(bufsize); + #region Property - Everything_SetSearch(query); - Everything_Query(); - // loop through the results, adding each result to the listbox. - for (i = 0; i < Everything_GetNumResults(); i++) + /// + /// Gets or sets a value indicating whether [match path]. + /// + /// true if [match path]; otherwise, false. + public Boolean MatchPath + { + get { - // get the result's full path and file name. - Everything_GetResultFullPathName(i, buf, bufsize); + return Everything_GetMatchPath(); } - } + set + { + Everything_SetMatchPath(value); + } + } + + /// + /// Gets or sets a value indicating whether [match case]. + /// + /// true if [match case]; otherwise, false. + public Boolean MatchCase + { + get + { + return Everything_GetMatchCase(); + } + set + { + Everything_SetMatchCase(value); + } + } + + /// + /// Gets or sets a value indicating whether [match whole word]. + /// + /// true if [match whole word]; otherwise, false. + public Boolean MatchWholeWord + { + get + { + return Everything_GetMatchWholeWord(); + } + set + { + Everything_SetMatchWholeWord(value); + } + } + + /// + /// Gets or sets a value indicating whether [enable regex]. + /// + /// true if [enable regex]; otherwise, false. + public Boolean EnableRegex + { + get + { + return Everything_GetRegex(); + } + set + { + Everything_SetRegex(value); + } + } + #endregion + + #region Public Method + /// + /// Resets this instance. + /// + public void Reset() + { + Everything_Reset(); + } + + /// + /// Searches the specified key word. + /// + /// The key word. + /// + public IEnumerable Search(string keyWord) + { + return Search(keyWord, 0, int.MaxValue); + } + + /// + /// Searches the specified key word. + /// + /// The key word. + /// The offset. + /// The max count. + /// + public IEnumerable Search(string keyWord, int offset, int maxCount) + { + if (string.IsNullOrEmpty(keyWord)) + throw new ArgumentNullException("keyWord"); + + if (offset < 0) + throw new ArgumentOutOfRangeException("offset"); + + if (maxCount < 0) + throw new ArgumentOutOfRangeException("maxCount"); + + Everything_SetSearch(keyWord); + Everything_SetOffset(offset); + Everything_SetMax(maxCount); + if (!Everything_Query()) + { + switch (Everything_GetLastError()) + { + case StateCode.CreateThreadError: + throw new CreateThreadException(); + case StateCode.CreateWindowError: + throw new CreateWindowException(); + case StateCode.InvalidCallError: + throw new InvalidCallException(); + case StateCode.InvalidIndexError: + throw new InvalidIndexException(); + case StateCode.IPCError: + throw new IPCErrorException(); + case StateCode.MemoryError: + throw new MemoryErrorException(); + case StateCode.RegisterClassExError: + throw new RegisterClassExException(); + } + yield break; + } + + const int bufferSize = 256; + StringBuilder buffer = new StringBuilder(bufferSize); + for (int idx = 0; idx < Everything_GetNumResults(); ++idx) + { + Everything_GetResultFullPathName(idx, buffer, bufferSize); + yield return buffer.ToString(); + } + } + #endregion + } + + + /// + /// + /// + public class MemoryErrorException : ApplicationException + { + } + + /// + /// + /// + public class IPCErrorException : ApplicationException + { + } + + /// + /// + /// + public class RegisterClassExException : ApplicationException + { + } + + /// + /// + /// + public class CreateWindowException : ApplicationException + { + } + + /// + /// + /// + public class CreateThreadException : ApplicationException + { + } + + /// + /// + /// + public class InvalidIndexException : ApplicationException + { + } + + /// + /// + /// + public class InvalidCallException : ApplicationException + { } } diff --git a/Plugins/WinAlfred.Plugin.Everything/Main.cs b/Plugins/WinAlfred.Plugin.Everything/Main.cs index eccd1246a3..f5c77e3512 100644 --- a/Plugins/WinAlfred.Plugin.Everything/Main.cs +++ b/Plugins/WinAlfred.Plugin.Everything/Main.cs @@ -9,17 +9,18 @@ namespace WinAlfred.Plugin.Everything { EverythingAPI api = new EverythingAPI(); - public string GetActionName() - { - return "ev"; - } - public List Query(Query query) { var results = new List(); - if (query.ActionParameters.Count > 0) + if (query.ActionParameters.Count > 0 && query.ActionParameters[0].Length > 0) { - api.Search(query.ActionParameters[0]); + IEnumerable enumerable = api.Search(query.ActionParameters[0]); + foreach (string s in enumerable) + { + Result r = new Result(); + r.Title = s; + results.Add(r); + } } return results; diff --git a/Plugins/WinAlfred.Plugin.Everything/WinAlfred.Plugin.Everything.csproj b/Plugins/WinAlfred.Plugin.Everything/WinAlfred.Plugin.Everything.csproj index 71739b3e00..1051a3c63e 100644 --- a/Plugins/WinAlfred.Plugin.Everything/WinAlfred.Plugin.Everything.csproj +++ b/Plugins/WinAlfred.Plugin.Everything/WinAlfred.Plugin.Everything.csproj @@ -20,6 +20,7 @@ DEBUG;TRACE prompt 4 + AnyCPU pdbonly @@ -29,6 +30,24 @@ prompt 4 + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + prompt + MinimumRecommendedRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + prompt + MinimumRecommendedRules.ruleset + diff --git a/Plugins/WinAlfred.Plugin.Everything/plugin.ini b/Plugins/WinAlfred.Plugin.Everything/plugin.ini new file mode 100644 index 0000000000..0b067a67ab --- /dev/null +++ b/Plugins/WinAlfred.Plugin.Everything/plugin.ini @@ -0,0 +1,8 @@ +[plugin] +ActionKeyword = ev +Name = everything +Author = qianlifeng +Version = 0.1 +Language = csharp +Description = test +ExecuteFile = WinAlfred.Plugin.Everything.dll diff --git a/WinAlfred.Plugin/IPlugin.cs b/WinAlfred.Plugin/IPlugin.cs index f33bf5346b..87a68f68ed 100644 --- a/WinAlfred.Plugin/IPlugin.cs +++ b/WinAlfred.Plugin/IPlugin.cs @@ -4,7 +4,6 @@ namespace WinAlfred.Plugin { public interface IPlugin { - string GetActionName(); List Query(Query query); void Init(); } diff --git a/WinAlfred.Plugin/Plugin.cs b/WinAlfred.Plugin/Plugin.cs new file mode 100644 index 0000000000..1d6a770f5e --- /dev/null +++ b/WinAlfred.Plugin/Plugin.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace WinAlfred.Plugin +{ + public class PluginPair + { + public IPlugin Plugin { get; set; } + public PluginMetadata Metadata { get; set; } + } +} diff --git a/WinAlfred.Plugin/PluginMetadata.cs b/WinAlfred.Plugin/PluginMetadata.cs index 0ce2b613b5..cdafc8e9e4 100644 --- a/WinAlfred.Plugin/PluginMetadata.cs +++ b/WinAlfred.Plugin/PluginMetadata.cs @@ -12,5 +12,7 @@ namespace WinAlfred.Plugin public string Version { get; set; } public string Language { get; set; } public string Description { get; set; } + public string ExecuteFile { get; set; } + public string ActionKeyword { get; set; } } } diff --git a/WinAlfred.Plugin/WinAlfred.Plugin.csproj b/WinAlfred.Plugin/WinAlfred.Plugin.csproj index 85273995a3..dae34c2341 100644 --- a/WinAlfred.Plugin/WinAlfred.Plugin.csproj +++ b/WinAlfred.Plugin/WinAlfred.Plugin.csproj @@ -20,6 +20,7 @@ DEBUG;TRACE prompt 4 + AnyCPU pdbonly @@ -29,6 +30,24 @@ prompt 4 + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + prompt + MinimumRecommendedRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + prompt + MinimumRecommendedRules.ruleset + @@ -40,6 +59,7 @@ + diff --git a/WinAlfred.sln b/WinAlfred.sln index c419cc7f78..17f5cfd839 100644 --- a/WinAlfred.sln +++ b/WinAlfred.sln @@ -14,25 +14,39 @@ EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU + Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU + Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {2770F339-701C-4698-8C9F-0FE007DFDFC5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2770F339-701C-4698-8C9F-0FE007DFDFC5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2770F339-701C-4698-8C9F-0FE007DFDFC5}.Debug|x86.ActiveCfg = Debug|Any CPU + {2770F339-701C-4698-8C9F-0FE007DFDFC5}.Debug|x86.Build.0 = Debug|Any CPU {2770F339-701C-4698-8C9F-0FE007DFDFC5}.Release|Any CPU.ActiveCfg = Release|Any CPU {2770F339-701C-4698-8C9F-0FE007DFDFC5}.Release|Any CPU.Build.0 = Release|Any CPU + {2770F339-701C-4698-8C9F-0FE007DFDFC5}.Release|x86.ActiveCfg = Release|Any CPU {FF742965-9A80-41A5-B042-D6C7D3A21708}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {FF742965-9A80-41A5-B042-D6C7D3A21708}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FF742965-9A80-41A5-B042-D6C7D3A21708}.Debug|x86.ActiveCfg = Debug|Any CPU {FF742965-9A80-41A5-B042-D6C7D3A21708}.Release|Any CPU.ActiveCfg = Release|Any CPU {FF742965-9A80-41A5-B042-D6C7D3A21708}.Release|Any CPU.Build.0 = Release|Any CPU + {FF742965-9A80-41A5-B042-D6C7D3A21708}.Release|x86.ActiveCfg = Release|Any CPU {8451ECDD-2EA4-4966-BB0A-7BBC40138E80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8451ECDD-2EA4-4966-BB0A-7BBC40138E80}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8451ECDD-2EA4-4966-BB0A-7BBC40138E80}.Debug|x86.ActiveCfg = Debug|Any CPU + {8451ECDD-2EA4-4966-BB0A-7BBC40138E80}.Debug|x86.Build.0 = Debug|Any CPU {8451ECDD-2EA4-4966-BB0A-7BBC40138E80}.Release|Any CPU.ActiveCfg = Release|Any CPU {8451ECDD-2EA4-4966-BB0A-7BBC40138E80}.Release|Any CPU.Build.0 = Release|Any CPU + {8451ECDD-2EA4-4966-BB0A-7BBC40138E80}.Release|x86.ActiveCfg = Release|Any CPU {230AE83F-E92E-4E69-8355-426B305DA9C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {230AE83F-E92E-4E69-8355-426B305DA9C0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {230AE83F-E92E-4E69-8355-426B305DA9C0}.Debug|x86.ActiveCfg = Debug|Any CPU + {230AE83F-E92E-4E69-8355-426B305DA9C0}.Debug|x86.Build.0 = Debug|Any CPU {230AE83F-E92E-4E69-8355-426B305DA9C0}.Release|Any CPU.ActiveCfg = Release|Any CPU {230AE83F-E92E-4E69-8355-426B305DA9C0}.Release|Any CPU.Build.0 = Release|Any CPU + {230AE83F-E92E-4E69-8355-426B305DA9C0}.Release|x86.ActiveCfg = Release|x86 + {230AE83F-E92E-4E69-8355-426B305DA9C0}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/WinAlfred/FrmMain.Designer.cs b/WinAlfred/FrmMain.Designer.cs index f0d93e2cc4..97ec853937 100644 --- a/WinAlfred/FrmMain.Designer.cs +++ b/WinAlfred/FrmMain.Designer.cs @@ -29,6 +29,7 @@ private void InitializeComponent() { this.tbQuery = new System.Windows.Forms.TextBox(); + this.listBox1 = new System.Windows.Forms.ListBox(); this.SuspendLayout(); // // tbQuery @@ -40,11 +41,21 @@ this.tbQuery.TabIndex = 0; this.tbQuery.TextChanged += new System.EventHandler(this.TbQuery_TextChanged); // + // listBox1 + // + this.listBox1.FormattingEnabled = true; + this.listBox1.ItemHeight = 12; + this.listBox1.Location = new System.Drawing.Point(12, 39); + this.listBox1.Name = "listBox1"; + this.listBox1.Size = new System.Drawing.Size(471, 352); + this.listBox1.TabIndex = 1; + // // FrmMain // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(495, 45); + this.ClientSize = new System.Drawing.Size(495, 404); + this.Controls.Add(this.listBox1); this.Controls.Add(this.tbQuery); this.MaximizeBox = false; this.MinimizeBox = false; @@ -61,6 +72,7 @@ #endregion private System.Windows.Forms.TextBox tbQuery; + private System.Windows.Forms.ListBox listBox1; } diff --git a/WinAlfred/FrmMain.cs b/WinAlfred/FrmMain.cs index 2c269ec258..c674a48adf 100644 --- a/WinAlfred/FrmMain.cs +++ b/WinAlfred/FrmMain.cs @@ -6,6 +6,7 @@ using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; +using WinAlfred.Helper; using WinAlfred.Plugin; using WinAlfred.PluginLoader; @@ -13,7 +14,7 @@ namespace WinAlfred { public partial class FrmMain : Form { - public List plugins = new List(); + public List plugins = new List(); private List results = new List(); public FrmMain() @@ -30,11 +31,34 @@ namespace WinAlfred private void TbQuery_TextChanged(object sender, EventArgs e) { results.Clear(); - foreach (IPlugin plugin in plugins) + foreach (PluginPair pair in plugins) { - results.AddRange(plugin.Query(new Query(tbQuery.Text))); + Query q = new Query(tbQuery.Text); + if (pair.Metadata.ActionKeyword == q.ActionName) + { + try + { + results.AddRange(pair.Plugin.Query(q)); + } + catch (Exception queryException) + { + Log.Error(string.Format("Plugin {0} query failed: {1}", pair.Metadata.Name, queryException.Message)); +#if (DEBUG) + { + throw; + } +#endif + throw; + } + } } var s = results.OrderByDescending(o => o.Score); + + listBox1.Items.Clear(); + foreach (Result result in results) + { + listBox1.Items.Add(result.Title); + } } } diff --git a/WinAlfred/Helper/Log.cs b/WinAlfred/Helper/Log.cs index 158245a088..6ac9dd363c 100644 --- a/WinAlfred/Helper/Log.cs +++ b/WinAlfred/Helper/Log.cs @@ -11,9 +11,9 @@ namespace WinAlfred.Helper { private static ILog fileLogger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - public static ILog FileLogger + public static void Error(string msg) { - get { return fileLogger; } + fileLogger.Error(msg); } } } diff --git a/WinAlfred/PluginLoader/BasePluginLoader.cs b/WinAlfred/PluginLoader/BasePluginLoader.cs index f408342717..dcdd672104 100644 --- a/WinAlfred/PluginLoader/BasePluginLoader.cs +++ b/WinAlfred/PluginLoader/BasePluginLoader.cs @@ -1,10 +1,8 @@ using System; using System.Collections.Generic; using System.IO; -using System.Reflection; using WinAlfred.Helper; using WinAlfred.Plugin; -using log4net; namespace WinAlfred.PluginLoader { @@ -14,14 +12,14 @@ namespace WinAlfred.PluginLoader private static string PluginConfigName = "plugin.ini"; protected static List pluginMetadatas = new List(); - public abstract List LoadPlugin(); + public abstract List LoadPlugin(); static BasePluginLoader() { ParsePlugins(); } - protected static void ParsePlugins() + private static void ParsePlugins() { ParseDirectories(); ParsePackagedPlugin(); @@ -32,8 +30,7 @@ namespace WinAlfred.PluginLoader string[] directories = Directory.GetDirectories(PluginPath); foreach (string directory in directories) { - string iniPath = directory + "\\" + PluginConfigName; - PluginMetadata metadata = GetMetadataFromIni(iniPath); + PluginMetadata metadata = GetMetadataFromIni(directory); if (metadata != null) pluginMetadatas.Add(metadata); } } @@ -43,11 +40,13 @@ namespace WinAlfred.PluginLoader } - private static PluginMetadata GetMetadataFromIni(string iniPath) + private static PluginMetadata GetMetadataFromIni(string directory) { + string iniPath = directory + "\\" + PluginConfigName; + if (!File.Exists(iniPath)) { - Log.FileLogger.Error(string.Format("parse plugin {0} failed: didn't find config file.", iniPath)); + Log.Error(string.Format("parse plugin {0} failed: didn't find config file.", iniPath)); return null; } @@ -61,10 +60,17 @@ namespace WinAlfred.PluginLoader metadata.Description = ini.GetSetting("plugin", "Description"); metadata.Language = ini.GetSetting("plugin", "Language"); metadata.Version = ini.GetSetting("plugin", "Version"); + metadata.ActionKeyword = ini.GetSetting("plugin", "ActionKeyword"); + metadata.ExecuteFile = AppDomain.CurrentDomain.BaseDirectory + directory + "\\" + ini.GetSetting("plugin", "ExecuteFile"); if (!AllowedLanguage.IsAllowed(metadata.Language)) { - Log.FileLogger.Error(string.Format("Parse ini {0} failed: invalid language {1}", iniPath, metadata.Language)); + Log.Error(string.Format("Parse ini {0} failed: invalid language {1}", iniPath, metadata.Language)); + return null; + } + if (!File.Exists(metadata.ExecuteFile)) + { + Log.Error(string.Format("Parse ini {0} failed: ExecuteFile didn't exist {1}", iniPath, metadata.ExecuteFile)); return null; } @@ -72,7 +78,7 @@ namespace WinAlfred.PluginLoader } catch (Exception e) { - Log.FileLogger.Error(string.Format("Parse ini {0} failed: {1}", iniPath, e.Message)); + Log.Error(string.Format("Parse ini {0} failed: {1}", iniPath, e.Message)); return null; } } diff --git a/WinAlfred/PluginLoader/CSharpPluginLoader.cs b/WinAlfred/PluginLoader/CSharpPluginLoader.cs index f9babbc38e..f736a6f443 100644 --- a/WinAlfred/PluginLoader/CSharpPluginLoader.cs +++ b/WinAlfred/PluginLoader/CSharpPluginLoader.cs @@ -1,18 +1,56 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Reflection; using System.Text; using WinAlfred.Helper; using WinAlfred.Plugin; namespace WinAlfred.PluginLoader { - public class CSharpPluginLoader:BasePluginLoader + public class CSharpPluginLoader : BasePluginLoader { - private List plugins = new List(); - - public override List LoadPlugin() + public override List LoadPlugin() { + List plugins = new List(); + + List metadatas = pluginMetadatas.Where(o => o.Language.ToUpper() == AllowedLanguage.CSharp.ToUpper()).ToList(); + foreach (PluginMetadata metadata in metadatas) + { + try + { + Assembly asm = Assembly.LoadFile(metadata.ExecuteFile); + List types = asm.GetTypes().Where(o => o.GetInterfaces().Contains(typeof(IPlugin))).ToList(); + if (types.Count == 0) + { + Log.Error(string.Format("Cound't load plugin {0}: didn't find the class who implement IPlugin", metadata.Name)); + continue; + } + if (types.Count > 1) + { + Log.Error(string.Format("Cound't load plugin {0}: find more than one class who implement IPlugin, there should only one class implement IPlugin", metadata.Name)); + continue; + } + + PluginPair pair = new PluginPair() + { + Plugin = Activator.CreateInstance(types[0]) as IPlugin, + Metadata = metadata + }; + plugins.Add(pair); + } + catch (Exception e) + { + Log.Error(string.Format("Cound't load plugin {0}: {1}", metadata.Name, e.Message)); +#if (DEBUG) +{ + throw; +} +#endif + } + + } + return plugins; } } diff --git a/WinAlfred/PluginLoader/PythonPluginLoader.cs b/WinAlfred/PluginLoader/PythonPluginLoader.cs index 588c7cffeb..8c702d3cef 100644 --- a/WinAlfred/PluginLoader/PythonPluginLoader.cs +++ b/WinAlfred/PluginLoader/PythonPluginLoader.cs @@ -2,18 +2,33 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using IronPython.Hosting; +using Microsoft.Scripting.Hosting; using WinAlfred.Helper; using WinAlfred.Plugin; namespace WinAlfred.PluginLoader { - public class PythonPluginLoader :BasePluginLoader + public class PythonPluginLoader : BasePluginLoader { - private List plugins = new List(); - public override List LoadPlugin() + public override List LoadPlugin() { + List plugins = new List(); + List metadatas = pluginMetadatas.Where(o => o.Language.ToUpper() == AllowedLanguage.Python.ToUpper()).ToList(); + foreach (PluginMetadata metadata in metadatas) + { + PythonPluginWrapper python = new PythonPluginWrapper(metadata.ExecuteFile); + PluginPair pair = new PluginPair() + { + Plugin = python, + Metadata = metadata + }; + plugins.Add(pair); + } return plugins; } + + } } diff --git a/WinAlfred/PluginLoader/PythonPluginWrapper.cs b/WinAlfred/PluginLoader/PythonPluginWrapper.cs new file mode 100644 index 0000000000..310e2d64eb --- /dev/null +++ b/WinAlfred/PluginLoader/PythonPluginWrapper.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using IronPython.Hosting; +using Microsoft.Scripting.Hosting; +using WinAlfred.Plugin; + +namespace WinAlfred.PluginLoader +{ + public class PythonPluginWrapper : IPlugin + { + private static ScriptEngine engine; + private static ScriptScope scope; + private object pythonInstance; + + static PythonPluginWrapper() + { + //creating engine and stuff + engine = Python.CreateEngine(); + scope = engine.CreateScope(); + + var paths = engine.GetSearchPaths(); + paths.Add(AppDomain.CurrentDomain.BaseDirectory + @"PythonEnv\2.7\Lib\"); + engine.SetSearchPaths(paths); + } + + public PythonPluginWrapper(string file) + { + pythonInstance = GetPythonClassInstance(file, "winAlfred"); + } + + private object GetPythonClassInstance(string file, string className) + { + ScriptSource source = engine.CreateScriptSourceFromFile(file); + CompiledCode compiled = source.Compile(); + + //now executing this code (the code should contain a class) + compiled.Execute(scope); + + //now creating an object that could be used to access the stuff inside a python script + return engine.Operations.Invoke(scope.GetVariable(className)); + } + + public List Query(Query query) + { + List results = new List(); + object invokeMember = engine.Operations.InvokeMember(pythonInstance, "query", query.RawQuery); + results.Add(new Result() + { + Title = invokeMember.ToString() + }); + return results; + } + + public void Init() + { + + } + } +} diff --git a/WinAlfred/WinAlfred.csproj b/WinAlfred/WinAlfred.csproj index e9f55f4d60..b8f6e47564 100644 --- a/WinAlfred/WinAlfred.csproj +++ b/WinAlfred/WinAlfred.csproj @@ -31,10 +31,52 @@ prompt 4 + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + prompt + MinimumRecommendedRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + prompt + MinimumRecommendedRules.ruleset + + + ..\packages\IronPython.2.7.4\lib\Net35\IronPython.dll + + + ..\packages\IronPython.2.7.4\lib\Net35\IronPython.Modules.dll + + + ..\packages\IronPython.2.7.4\lib\Net35\IronPython.SQLite.dll + ..\packages\log4net.2.0.3\lib\net35-full\log4net.dll + + ..\packages\IronPython.2.7.4\lib\Net35\Microsoft.Dynamic.dll + + + ..\packages\IronPython.2.7.4\lib\Net35\Microsoft.Scripting.dll + + + ..\packages\IronPython.2.7.4\lib\Net35\Microsoft.Scripting.AspNet.dll + + + ..\packages\IronPython.2.7.4\lib\Net35\Microsoft.Scripting.Core.dll + + + ..\packages\IronPython.2.7.4\lib\Net35\Microsoft.Scripting.Metadata.dll + @@ -57,6 +99,7 @@ + @@ -89,7 +132,6 @@ WinAlfred.Plugin -