這個問題由來已久,卻一直沒有找到原因。大家都知道,VisualStudio的DebuggerVisualizers是一個非常友善的插件,可以幫助我們調試時檢視Datatable視圖,前陣子突然發現在檢視時報錯了,截圖 如下:
詳細資訊裡的内容是:
view source print ?
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,還真找到了,具體位置在
view source print ?
1.
Common7IDEReferenceAssemblies
2
.0Microsoft.VisualStudio.DebuggerVisualizers.dll
當然,VS真正調的應該不是這個位置,從錯誤行49可以看出(實際上把這個位置的DebuggerVisualizers.dll删除照樣可以使用),是調的Windows下面的某個位置,這可能是寫到系統資料庫裡或者環境變量裡了,反正是這個dll不錯,但是vs使用的位置我沒法查到。用Reflector反編譯之,行7的CreateViewer源碼如下:
view source print ?
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 !=
))
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源碼如下:
view source print ?
01.
1
internal
static
unsafe
byte
[] MaybeDeserializeAndThrowException(
byte
[] data)
02.
2
{
03.
3
if
((data ==
null
) || (data.Length ==
))
04.
4
{
05.
5
return
null
;
06.
6
}
07.
7
DebugeeHost.DataPrefix prefix = (DebugeeHost.DataPrefix) data[
];
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,
, 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的枚舉如下:
view source print ?
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