定制Paste from Visual Studio插件(上)
2009-12-16 10:56 Jeffrey Zhao 阅读(6568) 评论(22) 编辑 收藏 举报我在上一篇文章里谈了我常用Paste from Visual Studio(下文称VSPaste)的插件,这大大方便了我写博客时贴代码的工作。不过今天早上有朋友在我博客后面留言说:“VSPaste没法显示行号,不知大家有没有办法解决?”其实这点很容易,写个小程序,把VSPaste生成的HTML再进行一番处理不就可以了嘛。不过最方便的做法还是让VSPaste直接生成带行号的代码块,不是吗?那么,我们就来自己动手丰衣足食解决这个问题吧。
这个问题说简单不简单,说复杂不复杂。其“不简单”之处在于VSPaste是不提供源代码的。而“不复杂”又在于……您一会儿就明白了。那么我们就开始吧,别担心,我和您一样不知道Windows Live Writer的插件体系。不过这不影响我们用正常的推理逻辑来解决问题。
了解VSPaste
第一步自然是要了解VSPaste插件,而这唯一的途径便是它的分发版本。您可以下载到VSPaste.msi文件,安装后就可以使用这个插件了。这个插件的部署原理很简单,只是在Windows Live Writer安装目录(如C:\Program Files\Windows Live\Writer\)的Plugins文件夹下放一个dll而已(话说这么容易的方式,为什么就非要提供一个安装文件?这么做很专业吗?),于是我们用.NET Refactor便可以打开这个文件一看究竟。
我相信您也会和我一样首先关注VSPaste类。于是我们查看打开它的CreateContent方法:
public class VSPaste { public override DialogResult CreateContent( IWin32Window dialogOwner, ref string newContent) { try { if (Clipboard.ContainsData(DataFormats.Rtf)) { newContent = "<pre class=\"code\">" + Undent( HTMLRootProcessor.FromRTF( (string)Clipboard.GetData(DataFormats.Rtf))) + "</pre><a href=\"http://11011.net/software/vspaste\"></a>"; return DialogResult.OK; } } catch { MessageBox.Show( "VS Paste could not convert that content.", "VS Paste Problem", MessageBoxButtons.OK, MessageBoxIcon.Hand); } return DialogResult.Cancel; } ... }
几乎没有比这再简单的逻辑了:我们在Visual Studio里复制了一段代码之后,这段文字会被保存为RTF格式,程序将其取出之后,再把它转化为HTML,最后在前后再加上些标签就行了。
尝试解决方案
VSPaste的难点其实是RTF到HTML的转化工作——这从来就是个难题,虽然已经有无数人投身于此。其实在一开始,我也并不想着要“修改”VSPaste,看到CreateContent这点代码相信您也觉得重新写一个更为简单。但是,打开HTMLRootProcessor.FromRTF方法之后我便放弃了,因为实在太复杂。然后我在网上找了找RTF转HTML的类库,还是找不到立即可可用的,于是最后还是下定决心从VSPaste入手。
如果要修改VSPaste,最方便的做法自然是将一个程序集的C#代码导出,而不少.NET Reflector的插件可以轻易完成这个工作。不过,您再回去看看程序集里的成员,就会发现其实这点并不容易。因为……编译后自动生成的一些类和成员,并无法再重新用C#编译器编译通过(主要是命名方面的问题)。不过可能经过简单的修改就行了,但我不知道——而且我们其实只要改一点点逻辑就行了,我不想搞那么复杂。既然如此,那么我们还是从IL入手吧。
别怕,我也不会IL。
要获得VSPaste程序集的IL,自然需要用到ildasm.exe,如下:
ildasm VSPaste.dll /output:VSPaste.il
于是我们就得到了VSPaste.il文件,您可以用某个文本编辑器打开,然后搜索CreateContent便可以定位到这个方法:
.method public hidebysig virtual instance valuetype [System....
CreateContent(class [System.Windows.Forms]System.Win...
string& newContent) cil managed...
{
// Code size 101 (0x65)
.maxstack 4
.locals init (valuetype [System.Windows.Forms]System.Windo...
bool V_1)
IL_0000: nop
.try
{
IL_0001: nop
IL_0002: ldsfld string [System.Windows.Forms]System...
IL_0007: call bool [System.Windows.Forms]System.W...
IL_000c: ldc.i4.0
IL_000d: ceq
IL_000f: stloc.1
IL_0010: ldloc.1
IL_0011: brtrue.s IL_0042
...
IL_0029: call string HTMLRootProcessor::FromRTF(string)
IL_002e: call string VSPaste.VSPaste::Undent(string)
IL_0033: ldstr "</pre><a href=\"http://11011.net/software/vspaste\"></a>"
IL_0038: call string [mscorlib]System.String::Concat(string,
string,
string)
...
好一堆“乱码”,不过其中可以定位到某些关键字符串,例如上面那行链接。那么我们先做一个尝试,把它去除如何?于是我们把不动其他内容,只是把那行代码修改成:
IL_0033: ldstr "</pre>"
OK,保存,然后使用ilasm.exe将其编译成VSPaste2.dll文件:
...>ilasm VSPaste.il /output:VSPaste2.dll /dll Microsoft (R) .NET Framework IL Assembler. Version 2.0.50727.4016 Copyright (c) Microsoft Corporation. All rights reserved. Assembling 'VSPaste.il' to DLL --> 'VSPaste2.dll' Source file is ANSI Assembled method VoidProcessor::Open Assembled method VoidProcessor::Close ... Class 7 Class 8 Class 9 Resolving local member refs: 0 -> 0 defs, 0 refs, 0 unresolved Writing PE file Operation completed successfully
好,关闭Windows Live Writer,再将VSPaste2.dll文件复制到Plugins目录下,然后重新打开Windows Live Writer,使用一下,是不是很有效?
谁说一定要学习IL才能摆弄这些,是不?
相关文章
- 定制Paste from Visual Studio插件(上)
- 定制Paste from Visual Studio插件(下)