[C#]Everything SDK
用過Everything也好一陣子了,一直以來都對他的快速搜尋有相當深刻的印象,但也只限於當作搜尋的工具之用,看了保哥介紹好用工具:Everything search engine (檔名搜尋工具)的這篇,發現原來該套軟體也有SDK可以使用,可藉由他的強大搜尋功能用來開發自己的工具,花點時間試著玩了一下,順手記錄一下。
SDK可在Download Everything這邊下載,內含C與C#的範例程式、DLL檔、以及C開發要用的標頭檔之類的檔案。Everything提供的是IPC類型的API,API的使用可參閱SDK - Wiki。這邊需注意到由於是IPC類型的API,故在使用時需確保Everything程式有被開啟。另外就是要確認SDK內的dll\Everything.dll是否有跟自己開發的程式放在一起。
為方便使用,這邊我又將API包了一層,除了一些控制搜尋的屬性外,最主要的就是Search方法,可提供搜尋我們所感興趣的資料:
using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Text; namespace Everything { /// <summary> /// /// </summary> public class EverythingAPI { #region Const const string EVERYTHING_DLL_NAME = "Everything.dll"; #endregion #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_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_NAME)] private static extern bool Everything_Query(); [DllImport(EVERYTHING_DLL_NAME)] private static extern void Everything_SortResultsByPath(); [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 #region Property /// <summary> /// Gets or sets a value indicating whether [match path]. /// </summary> /// <value><c>true</c> if [match path]; otherwise, <c>false</c>.</value> public Boolean MatchPath { get { return Everything_GetMatchPath(); } set { Everything_SetMatchPath(value); } } /// <summary> /// Gets or sets a value indicating whether [match case]. /// </summary> /// <value><c>true</c> if [match case]; otherwise, <c>false</c>.</value> public Boolean MatchCase { get { return Everything_GetMatchCase(); } set { Everything_SetMatchCase(value); } } /// <summary> /// Gets or sets a value indicating whether [match whole word]. /// </summary> /// <value><c>true</c> if [match whole word]; otherwise, <c>false</c>.</value> public Boolean MatchWholeWord { get { return Everything_GetMatchWholeWord(); } set { Everything_SetMatchWholeWord(value); } } /// <summary> /// Gets or sets a value indicating whether [enable regex]. /// </summary> /// <value><c>true</c> if [enable regex]; otherwise, <c>false</c>.</value> public Boolean EnableRegex { get { return Everything_GetRegex(); } set { Everything_SetRegex(value); } } #endregion #region Public Method /// <summary> /// Resets this instance. /// </summary> public void Reset() { Everything_Reset(); } /// <summary> /// Searches the specified key word. /// </summary> /// <param name="keyWord">The key word.</param> /// <returns></returns> public IEnumerable<string> Search(string keyWord) { return Search(keyWord, 0, int.MaxValue); } /// <summary> /// Searches the specified key word. /// </summary> /// <param name="keyWord">The key word.</param> /// <param name="offset">The offset.</param> /// <param name="maxCount">The max count.</param> /// <returns></returns> public IEnumerable<string> 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 } /// <summary> /// /// </summary> public class MemoryErrorException:ApplicationException { } /// <summary> /// /// </summary> public class IPCErrorException : ApplicationException { } /// <summary> /// /// </summary> public class RegisterClassExException : ApplicationException { } /// <summary> /// /// </summary> public class CreateWindowException : ApplicationException { } /// <summary> /// /// </summary> public class CreateThreadException : ApplicationException { } /// <summary> /// /// </summary> public class InvalidIndexException : ApplicationException { } /// <summary> /// /// </summary> public class InvalidCallException : ApplicationException { } }
使用上會像這個樣子:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; using System.Linq; using Everything; namespace WindowsApplication1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { EverythingAPI everyThingAPI = new EverythingAPI(); var results = everyThingAPI.Search(textBox1.Text); Text = textBox1.Text + " - " + results.Count() + " Results"; listBox1.Items.Clear(); foreach (var item in results) { listBox1.Items.Add(item); } } } }
運行結果如下:
Download