西西软件园多重安全检测下载网站、值得信赖的软件下载站!
软件
软件
文章
搜索

首页编程开发C#.NET → Paste from Visual Studio 插件中文乱码的解决方案

Paste from Visual Studio 插件中文乱码的解决方案

相关软件相关文章发表评论 来源:本站整理时间:2011/1/15 17:13:15字体大小:A-A+

作者:佚名点击:315次评论:0次标签: VisualStudio 插件

  • 类型:角色扮演大小:18.1M语言:中文 评分:.0
  • 标签:
立即下载
以前在 Windows Live Writer 中一直使用 Paste from Visual Studio 插件来在博文中粘贴代码。这个插件对 Visual Studio 2008 很好用,但是从 Visual Stduio 2010 中粘贴代码的话,每个中文字符后面,会跟着一个乱码,如下 ClipboardTester.cs 所示:

01: using System;
02: using System.Windows;
03:
04: namespace Skyiv.Tester
05: {
06: static class ClipboardTester
07: {
08: [STAThread]
09: static void Main()
10: {
11: var obj = Clipboard.GetDataObject();
12: foreach (var v in obj.GetFormats())
13: {
14: Console.WriteLine("[{0}]", v);
15: Console.WriteLine("-------- 开a始? --------");
16: try { Console.WriteLine("{0}", obj.GetData(v)); }
17: catch (Exception ex) { Console.WriteLine(ex); }
18: Console.WriteLine("-------- 结á束? --------");
19: Console.WriteLine();
20: }
21: }
22: }
23: }


我以前是手工一个个删除这些乱码。

查找根源
现在让我们来查找为什么会有乱码的原因吧。首先用以下命令编译上面给出的 ClipboardTester.cs 程序:

E:\CS\VSPaste> csc ClipboardTester.cs -r:C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF\PresentationCore.dll
Microsoft(R) Visual C# 2010 编译器 4.0.30319.1 版
版权所有(C) Microsoft Corporation。保留所有权利。


然后在 Visual Studio 2010 中使用“Ctrl-A”、“Ctrl-C”将这段源程序代码送到系统剪贴板,再运行 ClipboardTester.exe 从系统剪贴板中取出数据:

E:\CS\VSPaste> ClipboardTester
[Text]
-------- 开始 --------
using System;
using System.Windows;

namespace Skyiv.Tester
{
static class ClipboardTester
{
[STAThread]
static void Main()
{
var obj = Clipboard.GetDataObject();
foreach (var v in obj.GetFormats())
{
Console.WriteLine("[{0}]", v);
Console.WriteLine("-------- 开始 --------");
try { Console.WriteLine("{0}", obj.GetData(v)); }
catch (Exception ex) { Console.WriteLine(ex); }
Console.WriteLine("-------- 结束 --------");
Console.WriteLine();
}
}
}
}
-------- 结束 --------

[UnicodeText]
-------- 开始 --------
using System;
using System.Windows;

namespace Skyiv.Tester
{
static class ClipboardTester
{
[STAThread]
static void Main()
{
var obj = Clipboard.GetDataObject();
foreach (var v in obj.GetFormats())
{
Console.WriteLine("[{0}]", v);
Console.WriteLine("-------- 开始 --------");
try { Console.WriteLine("{0}", obj.GetData(v)); }
catch (Exception ex) { Console.WriteLine(ex); }
Console.WriteLine("-------- 结束 --------");
Console.WriteLine();
}
}
}
}
-------- 结束 --------

[System.String]
-------- 开始 --------
using System;
using System.Windows;

namespace Skyiv.Tester
{
static class ClipboardTester
{
[STAThread]
static void Main()
{
var obj = Clipboard.GetDataObject();
foreach (var v in obj.GetFormats())
{
Console.WriteLine("[{0}]", v);
Console.WriteLine("-------- 开始 --------");
try { Console.WriteLine("{0}", obj.GetData(v)); }
catch (Exception ex) { Console.WriteLine(ex); }
Console.WriteLine("-------- 结束 --------");
Console.WriteLine();
}
}
}
}
-------- 结束 --------

[Rich Text Format]
-------- 开始 --------
{\rtf\ansi{\fonttbl{\f0 NSimSun;}}{\colortbl;\red0\green0\blue255;\red43\green14
5\blue175;\red163\green21\blue21;}\f0 \fs19 \cf1 using\cf0 System;\par \cf1 usi
ng\cf0 System.Windows;\par \par \cf1 namespace\cf0 Skyiv.Tester\par \{\par \
cf1 static\cf0 \cf1 class\cf0 \cf2 ClipboardTester\cf0 \par \{\par [\cf2
STAThread\cf0 ]\par \cf1 static\cf0 \cf1 void\cf0 Main()\par \{\par
\cf1 var\cf0 obj = \cf2 Clipboard\cf0 .GetDataObject();\par \cf1 for
each\cf0 (\cf1 var\cf0 v \cf1 in\cf0 obj.GetFormats())\par \{\par
\cf2 Console\cf0 .WriteLine(\cf3 "[\{0\}]"\cf0 , v);\par \cf2 Console
\cf0 .WriteLine(\cf3 "-------- \uinput2\u24320 ?a\uinput2\u22987 ê? --------"\cf
0 );\par \cf1 try\cf0 \{ \cf2 Console\cf0 .WriteLine(\cf3 "\{0\}"\cf0 ,
obj.GetData(v)); \}\par \cf1 catch\cf0 (\cf2 Exception\cf0 ex) \{ \cf
2 Console\cf0 .WriteLine(ex); \}\par \cf2 Console\cf0 .WriteLine(\cf3 "-
------- \uinput2\u32467 ?á\uinput2\u26463 ê? --------"\cf0 );\par \cf2 C
onsole\cf0 .WriteLine();\par \}\par \}\par \}\par \}\par }
-------- 结束 --------

E:\CS\VSPaste>



从上面可以看出,出现乱码的根源在于 Visual Studio 2010 往系统剪贴板送 RTF 格式的内容时出错了。

修改 Paste from Visual Studio 插件
我们无法改变 Visual Studio 2010 的做法,只好修改 Paste from Visual Studio 插件了。以下步骤参照老赵的“定制 Paste from Visual Studio 插件”一文。

首先,使用 Reflector 查看 VSPaste.dll:





参照上图中的代码,编写一个 VSPaste2.cs:

01: using System;
02: using System.Windows.Forms;
03: using System.Text.RegularExpressions;
04:
05: public class HTMLRootProcessor
06: {
07: public static string FromRTF(string s) { return null; }
08: }
09:
10: namespace VSPaste
11: {
12: public class ContentSource
13: {
14: public virtual DialogResult CreateContent(IWin32Window dialogOwner, ref string newContent)
15: {
16: return DialogResult.Cancel;
17: }
18: }
19:
20: public class VSPaste : ContentSource
21: {
22: public static string Undent(string s) { return null; }
23:
24: public static string AddLines(string html)
25: {
26: string[] lines = html.Trim().Split('\n');
27: string pattern = "<span style=\"color:black; font-weight:bold;\">{0:" +
28: new String('0', lines.Length.ToString().Length) + "}: </span>";
29: for (int i = 0; i < lines.Length; i++)
30: lines[i] = String.Format(pattern, i + 1) + lines[i];
31: return String.Join("\n", lines);
32: }
33:
34: public static string DeleteChineseGarbage(string str)
35: {
36: return Regex.Replace(str, @"(?<ch>\\u\d+ )..", "${ch}?");
37: }
38:
39: public override DialogResult CreateContent(IWin32Window dialogOwner, ref string newContent)
40: {
41: try
42: {
43: if (Clipboard.ContainsData(DataFormats.Rtf))
44: {
45: string data = DeleteChineseGarbage((string)Clipboard.GetData(DataFormats.Rtf));
46: string str3 = AddLines(Undent(HTMLRootProcessor.FromRTF(data)));
47: newContent = "<pre class=\"code\">" + str3 + "</pre>";
48: return DialogResult.OK;
49: }
50: }
51: catch
52: {
53: MessageBox.Show("VS Paste could not convert that content.", "VS Paste Problem", MessageBoxButtons.OK, MessageBoxIcon.Hand);
54: }
55: return DialogResult.Cancel;
56: }
57: }
58: }


上述程序中,第 34 行到第 37 行的 DeleteChineseGarbage 方法用于删除中文乱码。第 45 行调用这个方法。用以下命令编译和反汇编:

E:\CS\VSPaste> csc /t:library VSPaste2.cs
Microsoft(R) Visual C# 2010 编译器 4.0.30319.1 版
版权所有(C) Microsoft Corporation。保留所有权利。

E:\CS\VSPaste> ildasm VSPaste2.dll /output:VSPaste2.il


得到的 VSPaste2.il 文件如下所示:

001: // Microsoft (R) .NET Framework IL Disassembler. Version 4.0.30319.1
002:
003:
004:
005:
006: // Metadata version: v2.0.50727
007: .assembly extern mscorlib
008: {
009: .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
010: .ver 2:0:0:0
011: }
012: .assembly extern System.Windows.Forms
013: {
014: .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
015: .ver 2:0:0:0
016: }
017: .assembly extern System
018: {
019: .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
020: .ver 2:0:0:0
021: }
022: .assembly VSPaste2
023: {
024: .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
025: .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
026: 63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows.
027: .hash algorithm 0x00008004
028: .ver 0:0:0:0
029: }
030: .module VSPaste2.dll
031: // MVID: {A944F44D-8C74-42FF-956B-B14EADD37E70}
032: .imagebase 0x00400000
033: .file alignment 0x00000200
034: .stackreserve 0x00100000
035: .subsystem 0x0003 // WINDOWS_CUI
036: .corflags 0x00000001 // ILONLY
037: // Image base: 0x00280000
038:
039:
040: // =============== CLASS MEMBERS DECLARATION ===================
041:
042: .class public auto ansi beforefieldinit HTMLRootProcessor
043: extends [mscorlib]System.Object
044: {
045: .method public hidebysig static string
046: FromRTF(string s) cil managed
047: {
048: // 代码大小 7 (0x7)
049: .maxstack 1
050: .locals init (string V_0)
051: IL_0000: nop
052: IL_0001: ldnull
053: IL_0002: stloc.0
054: IL_0003: br.s IL_0005
055:
056: IL_0005: ldloc.0
057: IL_0006: ret
058: } // end of method HTMLRootProcessor::FromRTF
059:
060: .method public hidebysig specialname rtspecialname
061: instance void .ctor() cil managed
062: {
063: // 代码大小 7 (0x7)
064: .maxstack 8
065: IL_0000: ldarg.0
066: IL_0001: call instance void [mscorlib]System.Object::.ctor()
067: IL_0006: ret
068: } // end of method HTMLRootProcessor::.ctor
069:
070: } // end of class HTMLRootProcessor
071:
072: .class public auto ansi beforefieldinit VSPaste.ContentSource
073: extends [mscorlib]System.Object
074: {
075: .method public hidebysig newslot virtual
076: instance valuetype [System.Windows.Forms]System.Windows.Forms.DialogResult
077: CreateContent(class [System.Windows.Forms]System.Windows.Forms.IWin32Window dialogOwner,
078: string& newContent) cil managed
079: {
080: // 代码大小 7 (0x7)
081: .maxstack 1
082: .locals init (valuetype [System.Windows.Forms]System.Windows.Forms.DialogResult V_0)
083: IL_0000: nop
084: IL_0001: ldc.i4.2
085: IL_0002: stloc.0
086: IL_0003: br.s IL_0005
087:
088: IL_0005: ldloc.0
089: IL_0006: ret
090: } // end of method ContentSource::CreateContent
091:
092: .method public hidebysig specialname rtspecialname
093: instance void .ctor() cil managed
094: {
095: // 代码大小 7 (0x7)
096: .maxstack 8
097: IL_0000: ldarg.0
098: IL_0001: call instance void [mscorlib]System.Object::.ctor()
099: IL_0006: ret
100: } // end of method ContentSource::.ctor
101:
102: } // end of class VSPaste.ContentSource
103:
104: .class public auto ansi beforefieldinit VSPaste.VSPaste
105: extends VSPaste.ContentSource
106: {
107: .method public hidebysig static string
108: Undent(string s) cil managed
109: {
110: // 代码大小 7 (0x7)
111: .maxstack 1
112: .locals init (string V_0)
113: IL_0000: nop
114: IL_0001: ldnull
115: IL_0002: stloc.0
116: IL_0003: br.s IL_0005
117:
118: IL_0005: ldloc.0
119: IL_0006: ret
120: } // end of method VSPaste::Undent
121:
122: .method public hidebysig static string
123: AddLines(string html) cil managed
124: {
125: // 代码大小 130 (0x82)
126: .maxstack 5
127: .locals init (string[] V_0,
128: string V_1,
129: int32 V_2,
130: string V_3,
131: char[] V_4,
132: int32 V_5,
133: bool V_6)
134: IL_0000: nop
135: IL_0001: ldarg.0
136: IL_0002: callvirt instance string [mscorlib]System.String::Trim()
137: IL_0007: ldc.i4.1
138: IL_0008: newarr [mscorlib]System.Char
139: IL_000d: stloc.s V_4
140: IL_000f: ldloc.s V_4
141: IL_0011: ldc.i4.0
142: IL_0012: ldc.i4.s 10
143: IL_0014: stelem.i2
144: IL_0015: ldloc.s V_4
145: IL_0017: callvirt instance string[] [mscorlib]System.String::Split(char[])
146: IL_001c: stloc.0
147: IL_001d: ldstr "<span style=\"color:black; font-weight:bold;\">{0:"
148: IL_0022: ldc.i4.s 48
149: IL_0024: ldloc.0
150: IL_0025: ldlen
151: IL_0026: conv.i4
152: IL_0027: stloc.s V_5
153: IL_0029: ldloca.s V_5
154: IL_002b: call instance string [mscorlib]System.Int32::ToString()
155: IL_0030: callvirt instance int32 [mscorlib]System.String::get_Length()
156: IL_0035: newobj instance void [mscorlib]System.String::.ctor(char,
157: int32)
158: IL_003a: ldstr "}: </span>"
159: IL_003f: call string [mscorlib]System.String::Concat(string,
160: string,
161: string)
162: IL_0044: stloc.1
163: IL_0045: ldc.i4.0
164: IL_0046: stloc.2
165: IL_0047: br.s IL_0066
166:
167: IL_0049: ldloc.0
168: IL_004a: ldloc.2
169: IL_004b: ldloc.1
170: IL_004c: ldloc.2
171: IL_004d: ldc.i4.1
172: IL_004e: add
173: IL_004f: box [mscorlib]System.Int32
174: IL_0054: call string [mscorlib]System.String::Format(string,
175: object)
176: IL_0059: ldloc.0
177: IL_005a: ldloc.2
178: IL_005b: ldelem.ref
179: IL_005c: call string [mscorlib]System.String::Concat(string,
180: string)
181: IL_0061: stelem.ref
182: IL_0062: ldloc.2
183: IL_0063: ldc.i4.1
184: IL_0064: add
185: IL_0065: stloc.2
186: IL_0066: ldloc.2
187: IL_0067: ldloc.0
188: IL_0068: ldlen
189: IL_0069: conv.i4
190: IL_006a: clt
191: IL_006c: stloc.s V_6
192: IL_006e: ldloc.s V_6
193: IL_0070: brtrue.s IL_0049
194:
195: IL_0072: ldstr "\n"
196: IL_0077: ldloc.0
197: IL_0078: call string [mscorlib]System.String::Join(string,
198: string[])
199: IL_007d: stloc.3
200: IL_007e: br.s IL_0080
201:
202: IL_0080: ldloc.3
203: IL_0081: ret
204: } // end of method VSPaste::AddLines
205:
206: .method public hidebysig static string
207: DeleteChineseGarbage(string str) cil managed
208: {
209: // 代码大小 22 (0x16)
210: .maxstack 3
211: .locals init (string V_0)
212: IL_0000: nop
213: IL_0001: ldarg.0
214: IL_0002: ldstr "(\?<ch>\\\\u\\d+ ).."
215: IL_0007: ldstr "${ch}\?"
216: IL_000c: call string [System]System.Text.RegularExpressions.Regex::Replace(string,
217: string,
218: string)
219: IL_0011: stloc.0
220: IL_0012: br.s IL_0014
221:
222: IL_0014: ldloc.0
223: IL_0015: ret
224: } // end of method VSPaste::DeleteChineseGarbage
225:
226: .method public hidebysig virtual instance valuetype [System.Windows.Forms]System.Windows.Forms.DialogResult
227: CreateContent(class [System.Windows.Forms]System.Windows.Forms.IWin32Window dialogOwner,
228: string& newContent) cil managed
229: {
230: // 代码大小 115 (0x73)
231: .maxstack 4
232: .locals init (string V_0,
233: string V_1,
234: valuetype [System.Windows.Forms]System.Windows.Forms.DialogResult V_2,
235: bool V_3)
236: IL_0000: nop
237: .try
238: {
239: IL_0001: nop
240: IL_0002: ldsfld string [System.Windows.Forms]System.Windows.Forms.DataFormats::Rtf
241: IL_0007: call bool [System.Windows.Forms]System.Windows.Forms.Clipboard::ContainsData(string)
242: IL_000c: ldc.i4.0
243: IL_000d: ceq
244: IL_000f: stloc.3
245: IL_0010: ldloc.3
246: IL_0011: brtrue.s IL_0050
247:
248: IL_0013: nop
249: IL_0014: ldsfld string [System.Windows.Forms]System.Windows.Forms.DataFormats::Rtf
250: IL_0019: call object [System.Windows.Forms]System.Windows.Forms.Clipboard::GetData(string)
251: IL_001e: castclass [mscorlib]System.String
252: IL_0023: call string VSPaste.VSPaste::DeleteChineseGarbage(string)
253: IL_0028: stloc.0
254: IL_0029: ldloc.0
255: IL_002a: call string HTMLRootProcessor::FromRTF(string)
256: IL_002f: call string VSPaste.VSPaste::Undent(string)
257: IL_0034: call string VSPaste.VSPaste::AddLines(string)
258: IL_0039: stloc.1
259: IL_003a: ldarg.2
260: IL_003b: ldstr "<pre class=\"code\">"
261: IL_0040: ldloc.1
262: IL_0041: ldstr "</pre>"
263: IL_0046: call string [mscorlib]System.String::Concat(string,
264: string,
265: string)
266: IL_004b: stind.ref
267: IL_004c: ldc.i4.1
268: IL_004d: stloc.2
269: IL_004e: leave.s IL_0070
270:
271: IL_0050: nop
272: IL_0051: leave.s IL_006b
273:
274: } // end .try
275: catch [mscorlib]System.Object
276: {
277: IL_0053: pop
278: IL_0054: nop
279: IL_0055: ldstr "VS Paste could not convert that content."
280: IL_005a: ldstr "VS Paste Problem"
281: IL_005f: ldc.i4.0
282: IL_0060: ldc.i4.s 16
283: IL_0062: call valuetype [System.Windows.Forms]System.Windows.Forms.DialogResult [System.Windows.Forms]System.Windows.Forms.MessageBox::Show(string,
284: string,
285: valuetype [System.Windows.Forms]System.Windows.Forms.MessageBoxButtons,
286: valuetype [System.Windows.Forms]System.Windows.Forms.MessageBoxIcon)
287: IL_0067: pop
288: IL_0068: nop
289: IL_0069: leave.s IL_006b
290:
291: } // end handler
292: IL_006b: nop
293: IL_006c: ldc.i4.2
294: IL_006d: stloc.2
295: IL_006e: br.s IL_0070
296:
297: IL_0070: nop
298: IL_0071: ldloc.2
299: IL_0072: ret
300: } // end of method VSPaste::CreateContent
301:
302: .method public hidebysig specialname rtspecialname
303: instance void .ctor() cil managed
304: {
305: // 代码大小 7 (0x7)
306: .maxstack 8
307: IL_0000: ldarg.0
308: IL_0001: call instance void VSPaste.ContentSource::.ctor()
309: IL_0006: ret
310: } // end of method VSPaste::.ctor
311:
312: } // end of class VSPaste.VSPaste
313:
314:
315: // =============================================================
316:
317: // *********** 反汇编完成 ***********************
318: // 警ˉ告: 创建了 Win32 资ê源文件 VSPaste2.res


现在,使用以下命令反汇编 VSPaste.dll:

E:\CS\VSPaste> ildasm VSPaste.dll /output:VSPaste.il



把 VSPaste2.il 文件中第 226 行到第 300 行的 VSPaste::CreateContent 方法替代 VSPaste.il 中的同名方法。并且把 VSPaste2.il 文件中第 206 行到第 224 行的 VSPate::DeleteChineseGarbage 方法加入到 VSPaste.il 文件中去。最后,使用以下命令重新进行汇编:

E:\CS\VSPaste> ilasm /dll /quiet VSPaste.il


将得到的 VSPaste.dll 拷贝到 Windows Live Writer 安装目录的 Plugins 目录,在我的机器上是 C:\Program Files\Windows Live\Writer\Plugins\,就行了。现在,让我们运行 Windows Live Writer,咦,VSPaste 插件不见了。怎么回事?

想了半天,最后使用 .NET Framework 2.0 中的 csc.exe 和 ilasm.exe 代替 .NET Framework 4 的,重做以上步骤。

在我的机器上,这两个 exe 文件位于 C:\Windows\Microsoft.NET\Framework\v2.0.50727\ 目录。而 ildasm.exe 还是使用 .NET Framework 4 的,因为没有找到 .NET Framework 2.0 的 ildasm.exe。

这下果然行了。

测试一下效果:

01: using System;
02: using System.Windows;
03:
04: namespace Skyiv.Tester
05: {
06: static class ClipboardTester
07: {
08: [STAThread]
09: static void Main()
10: {
11: var obj = Clipboard.GetDataObject();
12: foreach (var v in obj.GetFormats())
13: {
14: Console.WriteLine("[{0}]", v);
15: Console.WriteLine("-------- 开始 --------");
16: try { Console.WriteLine("{0}", VSPaste.VSPaste.DeleteChineseGarbage(obj.GetData(v).ToString())); }
17: catch (Exception ex) { Console.WriteLine(ex); }
18: Console.WriteLine("-------- 结束 --------");
19: Console.WriteLine();
20: }
21: }
22: }
23: }


果然没有乱码了。

另外一个 Paste from Visual Studio 插件
后来,又找到另外一个 Paste from Visual Studio 插件,效果如下:

ClipboardTester.cs
using System;
using System.Windows;

namespace Skyiv.Tester
{
static class ClipboardTester
{
[STAThread]
static void Main()
{
var obj = Clipboard.GetDataObject();
foreach (var v in obj.GetFormats())
{
Console.WriteLine("[{0}]", v);
Console.WriteLine("-------- 开始 --------");
try { Console.WriteLine("{0}", VSPaste.VSPaste.DeleteChineseGarbage(obj.GetData(v).ToString())); }
catch (Exception ex) { Console.WriteLine(ex); }
Console.WriteLine("-------- 结束 --------");
Console.WriteLine();
}
}
}
}

    相关评论

    阅读本文后您有什么感想? 已有人给出评价!

    • 8 喜欢喜欢
    • 3 顶
    • 1 难过难过
    • 5 囧
    • 3 围观围观
    • 2 无聊无聊

    热门评论

    最新评论

    发表评论 查看所有评论(0)

    昵称:
    表情: 高兴 可 汗 我不要 害羞 好 下下下 送花 屎 亲亲
    字数: 0/500 (您的评论需要经过审核才能显示)