热卡

迷上一个人,迷上一件事。

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

  这个问题由来已久,却一直没有找到原因。大家都知道,VisualStudio的DebuggerVisualizers是一个非常方便的插件,可以帮助我们调试时查看Datatable视图,前阵子突然发现在查看时报错了,截图 如下:

  详细信息里的内容是:

 1 有关调用实时(JIT)调试而不是此对话框的详细信息,
 2 请参见此消息的结尾。
 3 
 4 ************** 异常文本 **************
 5 System.Exception: 函数计算超时。
 6    在 Microsoft.VisualStudio.DebuggerVisualizers.DebugViewerShim.PrivateCallback.MaybeDeserializeAndThrowException(Byte[] data)
 7    在 Microsoft.VisualStudio.DebuggerVisualizers.DebugViewerShim.ManagedShim.DelegatedHost.CreateViewer(IntPtr hwnd, HostServicesHelper hsh, SafeProxyWrapper proxy)
 8 
 9 
10 ************** 已加载的程序集 **************
11 mscorlib
12     程序集版本:4.0.0.0
13     Win32 版本:4.0.30319.18444 built by: FX451RTMGDR
14     基本代码:file:///C:/Windows/Microsoft.NET/Framework/v4.0.30319/mscorlib.dll
15 ----------------------------------------
16 Microsoft.VisualStudio.Platform.AppDomainManager
17     程序集版本:12.0.0.0
18     Win32 版本:12.0.21005.1
19     基本代码:file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/Microsoft.VisualStudio.Platform.AppDomainManager/v4.0_12.0.0.0__b03f5f7f11d50a3a/Microsoft.VisualStudio.Platform.AppDomainManager.dll
20 ----------------------------------------
21 System
22     程序集版本:4.0.0.0
23     Win32 版本:4.0.30319.18408 built by: FX451RTMGREL
24     基本代码:file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System/v4.0_4.0.0.0__b77a5c561934e089/System.dll
25 ----------------------------------------
26 System.Configuration
27     程序集版本:4.0.0.0
28     Win32 版本:4.0.30319.18408 built by: FX451RTMGREL
29     基本代码:file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Configuration/v4.0_4.0.0.0__b03f5f7f11d50a3a/System.Configuration.dll
30 ----------------------------------------
31 System.Xml
32     程序集版本:4.0.0.0
33     Win32 版本:4.0.30319.34234 built by: FX452RTMGDR
34     基本代码:file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Xml/v4.0_4.0.0.0__b77a5c561934e089/System.Xml.dll
35 ----------------------------------------
36 System.Windows.Forms
37     程序集版本:4.0.0.0
38     Win32 版本:4.0.30319.18408 built by: FX451RTMGREL
39     基本代码:file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Windows.Forms/v4.0_4.0.0.0__b77a5c561934e089/System.Windows.Forms.dll
40 ----------------------------------------
41 System.Drawing
42     程序集版本:4.0.0.0
43     Win32 版本:4.0.30319.18408 built by: FX451RTMGREL
44     基本代码:file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Drawing/v4.0_4.0.0.0__b03f5f7f11d50a3a/System.Drawing.dll
45 ----------------------------------------
46 Microsoft.VisualStudio.DebuggerVisualizers
47     程序集版本:12.0.0.0
48     Win32 版本:12.0.21005.1
49     基本代码:file:///C:/Windows/assembly/GAC_MSIL/Microsoft.VisualStudio.DebuggerVisualizers/12.0.0.0__b03f5f7f11d50a3a/Microsoft.VisualStudio.DebuggerVisualizers.dll
50 ----------------------------------------
51 System.Windows.Forms.resources
52     程序集版本:4.0.0.0
53     Win32 版本:4.0.30319.18408 built by: FX451RTMGREL
54     基本代码:file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Windows.Forms.resources/v4.0_4.0.0.0_zh-Hans_b77a5c561934e089/System.Windows.Forms.resources.dll
55 ----------------------------------------
56 
57 ************** JIT 调试 **************
58 要启用实时(JIT)调试,
59 该应用程序或计算机的 .config 文件(machine.config)的 system.windows.forms 节中必须设置
60 jitDebugging 值。
61 编译应用程序时还必须启用
62 调试。
63 
64 例如:
65 
66 <configuration>
67     <system.windows.forms jitDebugging="true" />
68 </configuration>
69 
70 启用 JIT 调试后,任何未经处理的异常
71 都将被发送到在此计算机上注册的 JIT 调试器,
72 而不是由此对话框处理。
View Code

  从这个错误内容来看,最后抛出的是行6和行7,这是IDE绘制查看器弹窗时抛出的异常,我找了下这个dll,还真找到了,具体位置在

Common7\IDE\ReferenceAssemblies\v2.0\Microsoft.VisualStudio.DebuggerVisualizers.dll

  当然,VS真正调的应该不是这个位置,从错误行49可以看出(实际上把这个位置的DebuggerVisualizers.dll删除照样可以使用),是调的Windows下面的某个位置,这可能是写到注册表里或者环境变量里了,反正是这个dll不错,但是vs使用的位置我没法查到。用Reflector反编译之,行7的CreateViewer源码如下:

 1 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine), ResourceExposure(ResourceScope.None)]
 2 internal void CreateViewer(IntPtr hwnd, ManagedShim.HostServicesHelper hsh, ManagedShim.SafeProxyWrapper proxy)
 3 {
 4     try
 5     {
 6         byte[] data = proxy.InitSourceDataProvider();
 7         using (AssemblyResolver resolver = new HostResolver(proxy, hsh.IsRemote, new ServiceProvider.WindowWrapper(hwnd)))
 8         {
 9             string str;
10             string str2;
11             int num;
12             ASSEMBLYLOCRESOLUTION assemblylocresolution;
13             byte[] buffer;
14             byte[] buffer2;
15             PrivateCallback.MaybeDeserializeAndThrowException(data);
16             proxy.GetManagedViewerCreationData(out str, out buffer, out buffer2, out str2, out assemblylocresolution, out num);
17             if ((assemblylocresolution == ASSEMBLYLOCRESOLUTION.ALR_ERROR) && (str != null))
18             {
19                 throw new TerminalException(str, MessageBoxIcon.Hand);
20             }
21             if (((buffer != null) && (str == null)) && (hsh.IsRemote && !QueryRemoteLoadAllowed(null, new ServiceProvider.WindowWrapper(hwnd))))
22             {
23                 throw new TerminalException(MessageBoxIcon.Hand);
24             }
25             ClassAndAssemblySpec spec = new ClassAndAssemblySpec(str, buffer, assemblylocresolution != ASSEMBLYLOCRESOLUTION.ALR_NAME, str2);
26             DialogDebuggerVisualizer visualizer = (DialogDebuggerVisualizer) spec.CreateInstance(resolver);
27             using (PrivateCallback callback = new PrivateCallback(proxy, num != 0))
28             {
29                 visualizer.Show(new ServiceProvider(hwnd, hsh).DialogService, callback);
30             }
31         }
32     }
33     catch (TerminalException exception)
34     {
35         exception.DisplayDialog(new ServiceProvider.WindowWrapper(hwnd));
36     }
37     catch (Exception exception2)
38     {
39         new ThreadExceptionDialog(exception2).ShowDialog(new ServiceProvider.WindowWrapper(hwnd));
40     }
41 }
View Code

  从上面可以看出,走到行15就执行了异常处理,然后由PrivateCallback的MaybeDeserializeAndThrowException方法接管过来,MaybeDeserializeAndThrowException源码如下:

 1 internal static unsafe byte[] MaybeDeserializeAndThrowException(byte[] data)
 2 {
 3     if ((data == null) || (data.Length == 0))
 4     {
 5         return null;
 6     }
 7     DebugeeHost.DataPrefix prefix = (DebugeeHost.DataPrefix) data[0];
 8     switch (prefix)
 9     {
10         case DebugeeHost.DataPrefix.Exception:
11         {
12             Exception exception = (Exception) DeserializeObject(data, 1);
13             throw exception;
14         }
15         case DebugeeHost.DataPrefix.ObjectData:
16             return data;
17 
18         case DebugeeHost.DataPrefix.CustomExceptionData:
19         {
20             DebugeeHost.CustomExceptionDataHolder cedh = (DebugeeHost.CustomExceptionDataHolder) DeserializeObject(data, 1);
21             throw new RemoteObjectSourceException(cedh);
22         }
23         case DebugeeHost.DataPrefix.ErrorString:
24         case DebugeeHost.DataPrefix.ErrorStringNoHost:
25             if (data.Length < 8)
26             {
27                 throw new ApplicationException(SR.GetString("E_G_InvalidSerializationFormat"));
28             }
29             break;
30 
31         default:
32             return data;
33     }
34     fixed (byte* numRef = data)
35     {
36         int length = numRef[4];
37         if ((data.Length - 8) < (length * 2))
38         {
39             throw new ApplicationException(SR.GetString("E_G_InvalidSerializationFormat"));
40         }
41         char* chPtr = (char*) (numRef + 8);
42         string message = new string(chPtr, 0, length);
43         if (prefix == DebugeeHost.DataPrefix.ErrorStringNoHost)
44         {
45             throw new TerminalException(message, MessageBoxIcon.Exclamation);
46         }
47         throw new Exception(message);
48     }
49 }
View Code

  这里应该就是最后的“事发现场了”,其中case的枚举如下:

1 internal enum DataPrefix : byte
2 {
3     CustomExceptionData = 3,
4     ErrorString = 4,
5     ErrorStringNoHost = 5,
6     Exception = 1,
7     ObjectData = 2
8 }
View Code

  到此好像没法追踪下去了,它是通过传入的byte[]的0位值来抛出相应的异常,只有值为2或者default的时候才不抛出,由于没法模拟环境,即使我给了传入byte[],那么里面的调用层次还是要经过一番考究的。为此我也考虑了其他因素:

  1. 系统

  2. 硬件

  3. 内存

  4. 杀毒软件

  5. IDE本身

  6. 软件冲突

  7. 补丁

  8. IDE配置

  现在的现象是时好时坏,那么2、7就可以排除了,找了另外一台电脑,同样的系统同样的vs版本可以查看,那么1和5可以排除,内存用360释放一样有错,3可以排除,杀毒软件退掉依旧,4可以排除,6的话就麻烦了,难以查证,8的话也对比了正常的配置,没有差异,也可排除。

  现在比较有效的办法有两个:

  1、清理项目或者清理解决方案;

  2、杀进程,在任务管理器里结束与vs项目相关的host进程(不包括devenv.exe),如果有MSBuildTaskHost也要结束,然后再启动新实例,一般都能正常查看。

posted on 2014-12-31 15:58  热卡  阅读(1798)  评论(2编辑  收藏  举报