如何处理WinDbg中的“SOS版本与您正在debugging的CLR版本不匹配”?

我遇到了一些我的应用程序的问题。 这是在Windows 2003 Server(x86)的IIS6下运行的基于wcf的应用程序:
在事件日志中,我从“W3SVC-WP”源(EventID = 2262)得到这样的错误:

ISAPI 'C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll' reported itself as unhealthy for the following reason: 'Deadlock detected'. 

我正在试图弄清楚发生了什么事。 我已经build立了创build这个知识库中描述的孤儿工作进程的转储。 发生死锁时创build一个小型转储。
然后我用这个小转储来试着了解发生了什么。 这是我卡住了。

我运行WinDbg x86,打开我的转储,然后:

 0:037> .loadby sos clr 0:037> .sympath SRV*c:\temp\symbols*http://msdl.microsoft.com/download/symbols Symbol search path is: SRV*c:\temp\symbols*http://msdl.microsoft.com/download/symbols Expanded Symbol search path is: srv*c:\temp\symbols*http://msdl.microsoft.com/download/symbols 0:037> !clrstack The version of SOS does not match the version of CLR you are debugging. Please load the matching version of SOS for the version of CLR you are debugging. CLR Version: 4.0.30319.1 SOS Version: 4.0.30319.235 CLRDLL: C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\mscordacwks.dll:4.0.30319.235 f:8 doesn't match desired version 4.0.30319.01 f:8 CLRDLL: Loaded DLL c:\temp\symbols\mscordacwks_x86_x86_4.0.30319.01.dll\4BA1D9EF66f000\mscordacwks_x86_x86_4.0.30319.01.dll OS Thread Id: 0x690 (37) Unable to walk the managed stack. The current thread is likely not a managed thread. You can run !threads to get a list of managed threads in the process 

如何处理这个错误 – “SOS版本与您正在debugging的CLR版本不匹配”?

同样的错误(“SOS的版本不匹配您正在debugging的CLR的版本”)我得到当我在VS2010中打开小型转储。

我读过这篇文章 – http://tech-thinker.com/Forums/tabid/62/forumid/12/postid/471/scope/posts/Default.aspx ,并尝试安装KB2518870 。 这没有帮助。

WinDbg将无法使用debugging适配器mscordacwks.dll,除非它与原始机器的版本相同。 您可以通过从生成转储的目标计算机将此DLL复制到您的Windowsdebugging工具目录来解决此错误。

我们用WinDbgdebugging.NET 2.0应用程序。 我们会不断地得到这个mscordacwks_x86_x86_2.0.50727.3615.dll相同的错误。 我不得不将这个文件从服务器复制到我的客户端,并将其放在Windows(x86)\文件夹的C:\ Program Files \ Debugging Tools中。 WinDbg在此之后停止抱怨。

如果一切都失败了,你可以尝试使用WinDbg在你检索崩溃转储的同一台服务器上进行debugging。

这对我来说是有效的:

下载以下DLL:

  • clr.dll
  • mscordacwks.dll
  • SOS.dll

从生成转储的计算机上的以下文件夹中:

C:\ WINDOWS \ Microsoft.NET \ Framework64 \ v4.0.30319

运行以下命令。 SOS.DLL的path应该不带引号,未转义的path分隔符:

.loadpath下载SOS.DLL

我认为这个工作需要一个新的WinDbg会话。

核心问题通常在于mscordacwks.dll版本不匹配(如果发生完整转储,则不需要mscorwks.dll本身)。 从理论上说,它应该可以从符号服务器中获得 – 只需运行.cordll -ve -u -l 。 有关mscordacwks.dll更多信息,请参阅无法加载数据访问DLL,0x80004005“ – 或者 – 什么是mscordacwks.dll 。

不幸的是,某些版本的mscordacwks.dll没有被编入索引,这意味着上述不会总是工作。 在这种情况下,您可以尝试从获取转储的机器上获取正确的版本,例如Yocahi和Thomas提到的(例如,从C:\Windows\Microsoft.NET\Framework64\v4.0.30319 )。 一旦得到它,发出以下命令加载它: .cordll -u -ve -lp PathToFolderContainingMscorDAC 。 当然,这台机器可能无法访问,或者从转储开始的时候可能已经打上了补丁。

幸运的是,有一种方法可以从实际的更新KB软件包中提取mscorwdacwks.dll (它驻留在自解压可执行文件中的一个cab文件中 – 使用一个工具如7-Zip来提取它)。 还有一些.NET更新的版本库(由MS员工Doug Stewart提供),所以你可以浏览他们所需的确切版本号:

  • CLR 2.0的版本历史logging
  • CLR 4.0的版本历史logging

一旦你有了正确的mscordacwks.dll ,在大多数情况下SOS.dll警告可以被忽略,因为尽pipe有警告,最新的SOS.dll版本大部分时间都可以工作。 但是,在某些情况下,还需要正确的SOS.dll版本(作为奖励,您摆脱讨厌的警告)。 Dunken链接到一个博客文章 ,这应该是有帮助的(基本上你需要把符号服务器放在_NT_SYMBOL_PATH环境variables中,并运行!analyze –v 而不首先加载 SOS.dll – 它会自己加载正确的版本)。 如果这样做不起作用,您可以尝试从上述某个更新包中提取SOS.dll 。 这个网站可能更容易使用,因为它专门索引SOS.dll版本。

最后,考虑PsscorR2 (用于.NET 2.0-3.5 )和Psscor4 (用于.NET 4.0)。 PsscorPsscor的超集,它不会抱怨不匹配的版本,只要您使用适当的主版本即可。 需要注意的是,随着时间的推移,它还没有像SOS.dll一样被维护,所以后者可能包括前者缺less的增强和缺陷修复。 在写Psscor文章的时候,.NET 4.5没有Psscor版本。

 The version of SOS does not match the version of CLR you are debugging. Please load the matching version of SOS for the version of CLR you are debugging. CLR Version: 4.0.30319.1 SOS Version: 4.0.30319.235 

这意味着转储的目标机器正在运行CLR 4.0.30319.1版本。
您的系统正在运行版本4.0.30319.235

这是因为有一个.NET 4.0的安全更新,它改变了CLRSOS文件。 有些电脑可能还没有这个更新。

请参阅: http : //support.microsoft.com/kb/2572078

这可能会导致堆栈中的某些行有点错误…您可以通过获取原始版本的SOS.dllCLR.dllmscordacwks.dllmscorwks.dll并加载这些错误来避免错误加载SOS。
原始文件通常位于: C:\ Windows \ Microsoft.NET \ Framework \ v4.0.30319
取决于框架版本…然后将它们复制到特定的文件夹。
像这样加载正确的文件:

 .load C:\CurrectFiles\sos 

请注意,这只是“sos”而不是sos.dll。

您可以自动加载正确的SOS.dll。 看看John Robbins的博客文章http://wintellect.com/blogs/jrobbins/automatically-load-the-right-sos-for-the-minidump

你也可以检查.chain什么已经加载。 在某些情况下,您必须首先卸载(例如,卸载.unload sos )错误加载的dll。

总之,做到以下几点:

  1. 从转储获取CLR版本
  2. 查找并下载相应的Microsoft修补程序
  3. 从修补程序中提取sos.dllmscordacwks.dll
  4. 用它

下面是一个例子:

1.加载崩溃转储后,我得到我需要的版本:

 >lm vm clr 

它给了我

 File version: 4.0.30319.18051 

2.谷歌MS更新包含此版本:

sos.dll 4.0.30319.18051

在这种情况下,谷歌提供了一个MS KB页面下载链接。 我通常下载x64版本,因为它包含x86和x64 dll,所以我现在有Windows8-RT-KB2833958-x64.msu

注意:有时获取所需的修补程序非常困难,但在本例中不是。

3.使用FAR文件pipe理器,我从这个MSU提取机柜档案:

Windows8-RT-KB2833958-x64.cab

注意:有时候里面有几个机柜,所以你需要检查哪一个包含sos.dll。

注意:有时补丁是以.EXE的forms发布的,所以你首先需要提取MSU或者MSP文件(我用FAR来做),然后从中提取出机箱。

4.有时CAB中的文件可以通过FAR提取,但有时它们的结构会非常不同,我使用WinAIK中的 Expand.exe 。 WinAIK是1.7 Gb ISO,但你只需要一小部分。 我使用下面的BAT文件

 mkdir Extracted ..\winaik_amd64\servicing\Expand.exe "%1" -F:sos.dll "Extracted" ..\winaik_amd64\servicing\Expand.exe "%1" -F:mscordacwks.dll "Extracted" 

这个命令提取所有版本的指定dll,每个版本都在它自己的dir内。 有时候有两个版本的mscordacwks.dll和sos.dll。 我相信这是因为GRD / LDR(QFE)的工作人员。 在我们的例子中有4.0.30319。 180514.0.3031919079年 。 用Windows资源pipe理器检查文件属性。

5.适当重命名文件: mscordacwks.dll必须命名为mscordacwks_%arch%_%arch%_%version%.dll并放在sos.dll附近

所以mscordacwks.dll4.0.30319.18051 )去mscordacwks_AMD64_AMD64_4.0.30319.18051.dll

(x86版本重命名为mscordacwks_ x86_x86 _4.0.30319.18051.dll

sos.dll可能会保持原样,但我将其重命名为sos.4.0.30319.18051.dll

为4.0.30319.19079版本做同样的事情(为将来可能的需要)

6.将这些文件复制到“C:\ SOS \”文件夹中,其中包含许多sos.4.xxxdllmscordacwks_AMD64_AMD64_4.xxxdll

7.使用它

 .load C:\SOS\sos.4.0.30319.18051.dll 

注意:有时对于.Net 4.5,您需要向mscordacwks版本mscordacwks_AMD64_AMD64_4.6.1055添加附加的“0”。 00 .dll而不是mscordacwks_AMD64_AMD64_4.6.1055。 0 .dll。 尽pipe我没有深入,因为可以在很短的时间内处理这个问题。

顺便说一句,WinDbg会说,如果无法findmscordacwks,并将指定版本(将在最后双'0')。