这个问题由来已久,却一直没有找到原因。大家都知道,VisualStudio的DebuggerVisualizers是一个非常方便的插件,可以帮助我们调试时查看Datatable视图,前阵子突然发现在查看时报错了,截图 如下:
详细信息里的内容是:
01.
1
有关调用实时(JIT)调试而不是此对话框的详细信息,
02.
2
请参见此消息的结尾。
03.
3
04.
4
************** 异常文本 **************
05.
5
System.Exception: 函数计算超时。
06.
6
在 Microsoft.VisualStudio.DebuggerVisualizers.DebugViewerShim.PrivateCallback.MaybeDeserializeAndThrowException(Byte[] data)
07.
7
在 Microsoft.VisualStudio.DebuggerVisualizers.DebugViewerShim.ManagedShim.DelegatedHost.CreateViewer(IntPtr hwnd, HostServicesHelper hsh, SafeProxyWrapper proxy)
08.
8
09.
9
10.
10
************** 已加载的程序集 **************
11.
11
mscorlib
12.
12
程序集版本:
4.0
.
0.0
13.
13
<a href=
"http://www.it165.net/pro/"
target=
"_blank"
class
=
"keylink"
>Win32</a> 版本:
4.0
.
30319.18444
built by: FX451RTMGDR
14.
14
基本代码:file:
///C:/Windows/Microsoft.NET/Framework/v4.0.30319/mscorlib.dll
15.
15
----------------------------------------
16.
16
Microsoft.VisualStudio.Platform.AppDomainManager
17.
17
程序集版本:
12.0
.
0.0
18.
18
<a href=
"http://www.it165.net/pro/"
target=
"_blank"
class
=
"keylink"
>Win32</a> 版本:
12.0
.
21005.1
19.
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.
20
----------------------------------------
21.
21
System
22.
22
程序集版本:
4.0
.
0.0
23.
23
Win32 版本:
4.0
.
30319.18408
built by: FX451RTMGREL
24.
24
基本代码:file:
///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System/v4.0_4.0.0.0__b77a5c561934e089/System.dll
25.
25
----------------------------------------
26.
26
System.Configuration
27.
27
程序集版本:
4.0
.
0.0
28.
28
Win32 版本:
4.0
.
30319.18408
built by: FX451RTMGREL
29.
29
基本代码:file:
///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Configuration/v4.0_4.0.0.0__b03f5f7f11d50a3a/System.Configuration.dll
30.
30
----------------------------------------
31.
31
System.Xml
32.
32
程序集版本:
4.0
.
0.0
33.
33
Win32 版本:
4.0
.
30319.34234
built by: FX452RTMGDR
34.
34
基本代码:file:
///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Xml/v4.0_4.0.0.0__b77a5c561934e089/System.Xml.dll
35.
35
----------------------------------------
36.
36
System.Windows.Forms
37.
37
程序集版本:
4.0
.
0.0
38.
38
Win32 版本:
4.0
.
30319.18408
built by: FX451RTMGREL
39.
39
基本代码:file:
///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Windows.Forms/v4.0_4.0.0.0__b77a5c561934e089/System.Windows.Forms.dll
40.
40
----------------------------------------
41.
41
System.Drawing
42.
42
程序集版本:
4.0
.
0.0
43.
43
Win32 版本:
4.0
.
30319.18408
built by: FX451RTMGREL
44.
44
基本代码:file:
///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Drawing/v4.0_4.0.0.0__b03f5f7f11d50a3a/System.Drawing.dll
45.
45
----------------------------------------
46.
46
Microsoft.VisualStudio.DebuggerVisualizers
47.
47
程序集版本:
12.0
.
0.0
48.
48
Win32 版本:
12.0
.
21005.1
49.
49
基本代码:file:
///C:/Windows/assembly/GAC_MSIL/Microsoft.VisualStudio.DebuggerVisualizers/12.0.0.0__b03f5f7f11d50a3a/Microsoft.VisualStudio.DebuggerVisualizers.dll
50.
50
----------------------------------------
51.
51
System.Windows.Forms.resources
52.
52
程序集版本:
4.0
.
0.0
53.
53
Win32 版本:
4.0
.
30319.18408
built by: FX451RTMGREL
54.
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.
55
----------------------------------------
56.
56
57.
57
************** JIT 调试 **************
58.
58
要启用实时(JIT)调试,
59.
59
该应用程序或计算机的 .config 文件(machine.config)的 system.windows.forms 节中必须设置
60.
60
jitDebugging 值。
61.
61
编译应用程序时还必须启用
62.
62
调试。
63.
63
64.
64
例如:
65.
65
66.
66
<configuration>
67.
67
<system.windows.forms jitDebugging=
'true'
/>
68.
68
</configuration>
69.
69
70.
70
启用 JIT 调试后,任何未经处理的异常
71.
71
都将被发送到在此计算机上注册的 JIT 调试器,
72.
72
而不是由此对话框处理。
从这个错误内容来看,最后抛出的是行6和行7,这是IDE绘制查看器弹窗时抛出的异常,我找了下这个dll,还真找到了,具体位置在
1.
Common7IDEReferenceAssemblies
2
.0Microsoft.VisualStudio.DebuggerVisualizers.dll
当然,VS真正调的应该不是这个位置,从错误行49可以看出(实际上把这个位置的DebuggerVisualizers.dll删除照样可以使用),是调的Windows下面的某个位置,这可能是写到注册表里或者环境变量里了,反正是这个dll不错,但是vs使用的位置我没法查到。用Reflector反编译之,行7的CreateViewer源码如下:
01.
1
[ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine), ResourceExposure(ResourceScope.None)]
02.
2
internal
void
CreateViewer(IntPtr hwnd, ManagedShim.HostServicesHelper hsh, ManagedShim.SafeProxyWrapper proxy)
03.
3
{
04.
4
try
05.
5
{
06.
6
byte
[] data = proxy.InitSourceDataProvider();
07.
7
using (AssemblyResolver resolver =
new
HostResolver(proxy, hsh.IsRemote,
new
ServiceProvider.WindowWrapper(hwnd)))
08.
8
{
09.
9
string str;
10.
10
string str2;
11.
11
int
num;
12.
12
ASSEMBLYLOCRESOLUTION assemblylocresolution;
13.
13
byte
[] buffer;
14.
14
byte
[] buffer2;
15.
15
PrivateCallback.MaybeDeserializeAndThrowException(data);
16.
16
proxy.GetManagedViewerCreationData(out str, out buffer, out buffer2, out str2, out assemblylocresolution, out num);
17.
17
if
((assemblylocresolution == ASSEMBLYLOCRESOLUTION.ALR_ERROR) && (str !=
null
))
18.
18
{
19.
19
throw
new
TerminalException(str, MessageBoxIcon.Hand);
20.
20
}
21.
21
if
(((buffer !=
null
) && (str ==
null
)) && (hsh.IsRemote && !QueryRemoteLoadAllowed(
null
,
new
ServiceProvider.WindowWrapper(hwnd))))
22.
22
{
23.
23
throw
new
TerminalException(MessageBoxIcon.Hand);
24.
24
}
25.
25
ClassAndAssemblySpec spec =
new
ClassAndAssemblySpec(str, buffer, assemblylocresolution != ASSEMBLYLOCRESOLUTION.ALR_NAME, str2);
26.
26
DialogDebuggerVisualizer visualizer = (DialogDebuggerVisualizer) spec.CreateInstance(resolver);
27.
27
using (PrivateCallback callback =
new
PrivateCallback(proxy, num !=
0
))
28.
28
{
29.
29
visualizer.Show(
new
ServiceProvider(hwnd, hsh).DialogService, callback);
30.
30
}
31.
31
}
32.
32
}
33.
33
catch
(TerminalException exception)
34.
34
{
35.
35
exception.DisplayDialog(
new
ServiceProvider.WindowWrapper(hwnd));
36.
36
}
37.
37
catch
(Exception exception2)
38.
38
{
39.
39
new
ThreadExceptionDialog(exception2).ShowDialog(
new
ServiceProvider.WindowWrapper(hwnd));
40.
40
}
41.
41
}
从上面可以看出,走到行15就执行了异常处理,然后由PrivateCallback的MaybeDeserializeAndThrowException方法接管过来,MaybeDeserializeAndThrowException源码如下:
01.
1
internal
static
unsafe
byte
[] MaybeDeserializeAndThrowException(
byte
[] data)
02.
2
{
03.
3
if
((data ==
null
) || (data.Length ==
0
))
04.
4
{
05.
5
return
null
;
06.
6
}
07.
7
DebugeeHost.DataPrefix prefix = (DebugeeHost.DataPrefix) data[
0
];
08.
8
switch
(prefix)
09.
9
{
10.
10
case
DebugeeHost.DataPrefix.Exception:
11.
11
{
12.
12
Exception exception = (Exception) DeserializeObject(data,
1
);
13.
13
throw
exception;
14.
14
}
15.
15
case
DebugeeHost.DataPrefix.ObjectData:
16.
16
return
data;
17.
17
18.
18
case
DebugeeHost.DataPrefix.CustomExceptionData:
19.
19
{
20.
20
DebugeeHost.CustomExceptionDataHolder cedh = (DebugeeHost.CustomExceptionDataHolder) DeserializeObject(data,
1
);
21.
21
throw
new
RemoteObjectSourceException(cedh);
22.
22
}
23.
23
case
DebugeeHost.DataPrefix.ErrorString:
24.
24
case
DebugeeHost.DataPrefix.ErrorStringNoHost:
25.
25
if
(data.Length <
8
)
26.
26
{
27.
27
throw
new
ApplicationException(SR.GetString(
'E_G_InvalidSerializationFormat'
));
28.
28
}
29.
29
break
;
30.
30
31.
31
default
:
32.
32
return
data;
33.
33
}
34.
34
fixed (
byte
* numRef = data)
35.
35
{
36.
36
int
length = numRef[
4
];
37.
37
if
((data.Length -
8
) < (length *
2
))
38.
38
{
39.
39
throw
new
ApplicationException(SR.GetString(
'E_G_InvalidSerializationFormat'
));
40.
40
}
41.
41
char
* chPtr = (
char
*) (numRef +
8
);
42.
42
string message =
new
string(chPtr,
0
, length);
43.
43
if
(prefix == DebugeeHost.DataPrefix.ErrorStringNoHost)
44.
44
{
45.
45
throw
new
TerminalException(message, MessageBoxIcon.Exclamation);
46.
46
}
47.
47
throw
new
Exception(message);
48.
48
}
49.
49
}
这里应该就是最后的“事发现场了”,其中case的枚举如下:
1.
1
internal
enum
DataPrefix :
byte
2.
2
{
3.
3
CustomExceptionData =
3
,
4.
4
ErrorString =
4
,
5.
5
ErrorStringNoHost =
5
,
6.
6
Exception =
1
,
7.
7
ObjectData =
2
8.
8
}
到此好像没法追踪下去了,它是通过传入的byte[]的0位值来抛出相应的异常,只有值为2或者default的时候才不抛出,由于没法模拟环境,即使我给了传入byte[],那么里面的调用层次还是要经过一番考究的。为此我也考虑了其他因素:
系统
硬件
内存
杀毒软件
IDE本身
软件冲突
补丁
IDE配置
现在的现象是时好时坏,那么2、7就可以排除了,找了另外一台电脑,同样的系统同样的vs版本可以查看,那么1和5可以排除,内存用360释放一样有错,3可以排除,杀毒软件退掉依旧,4可以排除,6的话就麻烦了,难以查证,8的话也对比了正常的配置,没有差异,也可排除。
现在比较有效的办法是杀进程,在任务管理器里结束与vs项目相关的host进程(不包括devenv.exe),如果有MSBuildTaskHost也要结束,然后再启动新实例,一般都能正常查看。
转载地址:http://www.it165.net/pro/html/201501/30763.html