以前用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/ 

posted on 2012-07-28 21:53  一风  阅读(3776)  评论(3编辑  收藏  举报