一:背景
1. 讲故事
在最近一两年内Visual Studio 2022会偶发的出现打开即崩溃的情况,本想着把VS卸载重装,但发现这东西想卸载干净还是蛮困难的,又加上我这个人比较懒,所以就直接重装系统了,最近的9月份因为它重装了一次系统,但过了一天又遇到了同样的问题,在这样一个背景下我决定认真的看下到底是什么回事?毕竟一直装系统也不是个事。
二:崩溃分析
1. 崩溃现象
打开VisualStudio之后,会弹出错误信息 Exception has been thrown by the target of an invocation.
大概意思就是在调用目标上发生了异常,截图如下:
熟悉我的朋友都知道,我个人喜欢用 procdump 来捕获异常,这里可以根据指定异常的方式获取,参考命令和截图如下:
procdump -w devenv -e 1 -f TargetInvocationException -ma -o D:\testdump\
从图中的子异常TypeLoadException
来看,看样子是加载了某个类型出错的,这里要提醒一下,上面的乱码是因为中文操作系统解析不了这些字符,大家可以把操作系统改成 英文版的,就可以显示全部字符,参考如下:
2. windbg分析
dump成功抓到之后,接下来就是启动 windbg 分析了,因为是托管层抛出的异常,直接用 !t
观察即可。
0:000> !t
ThreadCount: 22
UnstartedThread: 0
BackgroundThread: 20
PendingThread: 0
DeadThread: 2
Hosted Runtime: no
Lock
ID OSID ThreadOBJ State GC Mode GC Alloc Context Domain Count Apt Exception
0 1 2840 000001ac95d47e20 a4228 Preemptive 000001AC97806580:000001AC97807218 000001ac95d3a9d0 2 STA System.Reflection.TargetInvocationException 000001ac97804c28
9 2 31d0 000001ac95da3d60 2b228 Preemptive 000001ACD6F92F00:000001ACD6F94E88 000001ac95d3a9d0 0 MTA (Finalizer)
...
从卦中可以清晰的看到确实存在一个异常,接下来使用 pe 来观察异常详情,参考如下:
0:000> !pe -nested 000001ac97804c28
Exception object: 000001ac97804c28
Exception type: System.Reflection.TargetInvocationException
Message: Exception has been thrown by the target of an invocation.
InnerException: System.TypeInitializationException, Use !PrintException 000001ac97804838 to see more.
StackTrace (generated):
SP IP Function
0000008618CFC6E0 0000000000000000 mscorlib_ni!System.RuntimeFieldHandle.GetValue(System.Reflection.RtFieldInfo, System.Object, System.RuntimeType, System.RuntimeType, Boolean ByRef)+0xffff80024c1d3360
0000008618CFC6E0 00007FFDB2CA9F03 mscorlib_ni!System.Reflection.RtFieldInfo.UnsafeGetValue(System.Object)+0xa3
StackTraceString: <none>
HResult: 80131604
0:000> !PrintException /d 000001ac97804838
Exception object: 000001ac97804838
Exception type: System.TypeInitializationException
Message: The type initializer for 'System.Windows.Automation.Peers.AutomationPeer' threw an exception.
InnerException: System.TypeLoadException, Use !PrintException 000001ac978003e8 to see more.
StackTrace (generated):
<none>
StackTraceString: <none>
HResult: 80131534
0:000> !PrintException /d 000001ac978003e8
Exception object: 000001ac978003e8
Exception type: System.TypeLoadException
Message: 程序集“PresentationCore, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35”中的类型“MS.Internal.Automation.SelectionProviderWrapper”的方法“GetSelection”没有实现。
InnerException: <none>
StackTrace (generated):
SP IP Function
0000008618CFB520 0000000000000000 PresentationCore!System.Windows.Automation.Peers.AutomationPeer.Initialize()+0x1
0000008618CFB5D0 00007FFD55FDD431 PresentationCore!System.Windows.Automation.Peers.AutomationPeer..cctor()+0x81
StackTraceString: <none>
HResult: 80131522
从卦中可以清晰的看到,原来是SelectionProviderWrapper 类没有 GetSelection 实现
,虽然找到了错误原因,但vs不是我们写的,无法修改源码,这个时候直接拿错误信息去网上找咯。
3. 寻找沦落人
在网络上一顿找,终于在 wpf 的仓库里给找到了,链接如下:https://github.com/dotnet/wpf/issues/8056
根据文章描述需要卸载 KB5011048
补丁即可,打开系统补丁列表,还真的有,果断给卸载掉。
卸载完成之后,重启操作系统,我去,还真的就打开了。
4. 为什么会这样
要想找到原因得要知道 KB5011048
补丁是用来干嘛的,链接如下:https://support.microsoft.com/zh-cn/topic/microsoft-net-framework-4-8-1-%E9%80%82%E7%94%A8%E4%BA%8E-windows-10-%E7%89%88%E6%9C%AC-21h2-windows-10-%E7%89%88%E6%9C%AC-22h2-windows-11-%E7%89%88%E6%9C%AC-21h2-windows-server-2022-desktop-azure-editions-azure-stack-21h2-%E5%92%8C-azure-stack-22h2-kb5011048-277f9c30-7add-4150-b774-5e3667e02256#:~:text=Microsoft%20.NET%20Framework%204.8.1%20(KB5011048)
从 MSDN 的描述来看,这个补丁和 .NET Framework 4.8.1
有关,而且还特别提到了 高度兼容
,看样子没有高度兼容。
到这里我大概就知道了来龙去脉,VS 用的是 .NETFramwork 4.8 ,但这个补丁导致Windows底层库更新到了 4.8.1, 结果 VS 使用的 GetSelection 方法在新的底层库中找不到方法实现了,最终导致 VS 直接崩溃。
三:总结
这次Visual Studio 2022 的启动崩溃罪魁祸首居然是 Windows 的补丁包导致的,这也太不靠谱了吧,不过这个案例也告诉我们有时候掌握一点dump分析能力,还是很容易找到问题的突破口。