以前用VS一直不知道自訂工具這傢伙是幹什麼用的,後來漸漸明白是用來產生代碼的。現在一個項目需要將一個自訂格式的XML轉換為代碼,就想到要自己做一個自訂工具來產生代碼,於是找了網上一些資料,終於開發成功。
第一步,編寫代碼
在VS裡建立一個類庫,這與一般的過程沒什麼兩樣,然後需要添加兩個DLL的引用,一個是Microsoft.VisualStudio.Shell.Interop.DLL,另一個是Microsoft.VisualStudio.Shell.DLL。但奇怪的是,這兩個DLL並沒有出現在添加引用的對話方塊裡,我找了很久,最後還是直接從GAC的目錄裡複製出來的。
接下來,建立一個類,這個類需要實現IVsSingleFileGenerator介面。關於介面的詳細說明,請參考MSDN。這個介面有兩個成員,一個是DefaultExtension,用來擷取所組建檔案的副檔名,另一個是Generate,就是需要實現代碼產生的地方了。來看一下我的測試代碼,這些代碼是從Code Project上複製過來的。
View Code
public class LineCountGenerator : IVsSingleFileGenerator
{
public int DefaultExtension(out string pbstrDefaultExtension)
{
pbstrDefaultExtension = ".txt";
return pbstrDefaultExtension.Length;
}
public int Generate(string wszInputFilePath, string bstrInputFileContents, string wszDefaultNamespace, IntPtr[] rgbOutputFileContents, out uint pcbOutput, IVsGeneratorProgress pGenerateProgress)
{
int lineCount = bstrInputFileContents.Split('\n').Length;
byte[] bytes = Encoding.UTF8.GetBytes(lineCount.ToString());
int length = bytes.Length;
rgbOutputFileContents[0] = Marshal.AllocCoTaskMem(length);
Marshal.Copy(bytes, 0, rgbOutputFileContents[0], length);
pcbOutput = (uint)length;
return VSConstants.S_OK;
}
}
稍微解釋一下,這個產生器的作用就是將源檔案的行數寫入到一個文字檔中。來看Generate方法的實現,首先從源檔案中分析出行數,但我們無法將這個資訊以傳統的.net方式寫入輸出檔案中,而是要通過Marshal與非託管的VS交換資料。這就需要把行數轉換成字串後獲得相應的位元組數組,再將這個位元組數組寫入到從系統分配來的COM任務記憶體中。所分配的記憶體不需要我們去釋放,VS會替我們搞定的。(其實COM我並不懂,照樣做准沒錯就是了)
第二步,準備程式集
因為自訂工具必須是一個COM組件,所以還需要把DLL設定為COM可見,這個很容易,在Properties目錄的AssemblyInfo.cs中,把ComVisible的參數改為true。然後為剛才的LineCountGenerator加上一個GuidAttribute就可以了。
程式必須要放在GAC裡才能被VS直接調用,而程式集必須要進行簽名才能放入GAC,所以我們還得為DLL進行簽名。只需要在項目的屬性裡做一個簡單的設定就可以了,當然不嫌麻煩的話也可以用sn.exe。
接下來,編譯後,開啟VS的命令提示字元,然後轉到程式集所在的目錄,分別用regasm和gacutil對所產生的DLL進行註冊。
第三步,讓VS知道
VS通過註冊表存放自訂工具的資訊,位置在:
32位:HKLM\Software\Microsoft\VisualStudio\版本\Generators\語言
64位:HKLM\Software\Wow6432Node\Microsoft\VisualStudio\版本\Generators\語言
其中,版本就你當前所使用的VS的版本號碼,2010是10.0,2008是9.0。語言就是程式開發語言的GUID,對於C#來說,是{FAE04EC1-301F-11D3-BF4B-00C04F79EFBC}。
通過登錄編輯程式開啟後,你會看到下面已經有一些自訂工具了,不解析,照葫蘆畫瓢就可以了。
第四步,使用自訂工具
到此為止,自訂工具已經搞定,接下來就是使用它了。很簡單,在解決方案瀏覽器中某個檔案的屬性裡,在自訂工具一欄中輸入工具的名稱就可以了。不要問我應該輸入什麼內容,折騰了老半天你應該知道的。 輸入之後敲斷行符號,你會發現加號下面多了一個檔案,哈哈,這就是我們的代碼產生。
因為時間關係,我沒有將整個過程寫得很細緻,考慮到有這種需求的人應該有一定的基礎,所以我就省點口水了,呵呵。下面列出幾篇參考文章,有不明白的地方可以去看看,我也是從這裡面學出來的。
http://www.codeproject.com/Articles/31257/Custom-Tools-Explained
http://msdn.microsoft.com/en-us/library/bb166817.aspx
http://www.drewnoakes.com/snippets/WritingACustomCodeGeneratorToolForVisualStudio/