首页 > 代码库 > VS2010Datatable查看器查看超时(Microsoft.VisualStudio.DebuggerVisualizers)

VS2010Datatable查看器查看超时(Microsoft.VisualStudio.DebuggerVisualizers)

  这个问题由来已久,却一直没有找到原因。大家都知道,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 mscorlib12     程序集版本:4.0.0.013     Win32 版本:4.0.30319.18444 built by: FX451RTMGDR14     基本代码:file:///C:/Windows/Microsoft.NET/Framework/v4.0.30319/mscorlib.dll15 ----------------------------------------16 Microsoft.VisualStudio.Platform.AppDomainManager17     程序集版本:12.0.0.018     Win32 版本:12.0.21005.119     基本代码:file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/Microsoft.VisualStudio.Platform.AppDomainManager/v4.0_12.0.0.0__b03f5f7f11d50a3a/Microsoft.VisualStudio.Platform.AppDomainManager.dll20 ----------------------------------------21 System22     程序集版本:4.0.0.023     Win32 版本:4.0.30319.18408 built by: FX451RTMGREL24     基本代码:file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System/v4.0_4.0.0.0__b77a5c561934e089/System.dll25 ----------------------------------------26 System.Configuration27     程序集版本:4.0.0.028     Win32 版本:4.0.30319.18408 built by: FX451RTMGREL29     基本代码:file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Configuration/v4.0_4.0.0.0__b03f5f7f11d50a3a/System.Configuration.dll30 ----------------------------------------31 System.Xml32     程序集版本:4.0.0.033     Win32 版本:4.0.30319.34234 built by: FX452RTMGDR34     基本代码:file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Xml/v4.0_4.0.0.0__b77a5c561934e089/System.Xml.dll35 ----------------------------------------36 System.Windows.Forms37     程序集版本:4.0.0.038     Win32 版本:4.0.30319.18408 built by: FX451RTMGREL39     基本代码:file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Windows.Forms/v4.0_4.0.0.0__b77a5c561934e089/System.Windows.Forms.dll40 ----------------------------------------41 System.Drawing42     程序集版本:4.0.0.043     Win32 版本:4.0.30319.18408 built by: FX451RTMGREL44     基本代码:file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Drawing/v4.0_4.0.0.0__b03f5f7f11d50a3a/System.Drawing.dll45 ----------------------------------------46 Microsoft.VisualStudio.DebuggerVisualizers47     程序集版本:12.0.0.048     Win32 版本:12.0.21005.149     基本代码:file:///C:/Windows/assembly/GAC_MSIL/Microsoft.VisualStudio.DebuggerVisualizers/12.0.0.0__b03f5f7f11d50a3a/Microsoft.VisualStudio.DebuggerVisualizers.dll50 ----------------------------------------51 System.Windows.Forms.resources52     程序集版本:4.0.0.053     Win32 版本:4.0.30319.18408 built by: FX451RTMGREL54     基本代码: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.dll55 ----------------------------------------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 而不是由此对话框处理。

从这个错误内容来看,最后抛出的是行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 =http://www.mamicode.com/ 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 }

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

 1 internal static unsafe byte[] MaybeDeserializeAndThrowException(byte[] data) 2 { 3     if ((data =http://www.mamicode.com/= 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 }

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

1 internal enum DataPrefix : byte2 {3     CustomExceptionData = http://www.mamicode.com/3,4     ErrorString = 4,5     ErrorStringNoHost = 5,6     Exception = 1,7     ObjectData = http://www.mamicode.com/28 }

  到此好像没法追踪下去了,它是通过传入的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的话也对比了正常的配置,没有差异,也可排除。

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

VS2010Datatable查看器查看超时(Microsoft.VisualStudio.DebuggerVisualizers)