Total Commander 主线程卡死问题排查
Total Commander 主线程卡死问题排查——百度网盘 Shell 扩展你搁这等啥呢Total Commander 主线程卡死问题排查问题现象排查工具排查步骤第一步给卡死的进程拍个遗照生成 Dump第二步请出 WinDbg 大夫加载 Dump第三步看看这是啥类型的 Dump第四步翻主线程的调用栈破案关键第五步确认凶手身份根因分析调用链还原来龙去脉解决方案方案一打开百度网盘设置禁用 Shell 扩展推荐方案二卸载百度网盘Total Commander 主线程卡死问题排查问题现象某天正愉快地用 Total Commander64位管理文件右键一点……好家伙整个界面直接石化鼠标转圈圈窗口标题栏写着大大的未响应。只能含泪打开任务管理器把它送走。用 PowerShell 确认一下果然凉了Get-Process-NameTOTALCMD64|Select-ObjectId,ProcessName,Responding输出Id ProcessName Responding -- ----------- ---------- 1234 TOTALCMD64 FalseResponding False实锤了——主线程消息循环彻底罢工。排查工具工具干啥用的PowerShell确认进程状态、生成 dump 文件WinDbg打开 dump 文件翻线程调用栈找凶手dbghelp.dll提供MiniDumpWriteDumpAPI用来给进程拍快照排查步骤第一步给卡死的进程拍个遗照生成 Dump进程卡死了但没崩系统不会自动生成 dump得我们自己动手。写个 PowerShell 脚本dump.ps1Add-Type-TypeDefinition using System; using System.Runtime.InteropServices; public class MiniDumpHelper { [DllImport(dbghelp.dll, SetLastError true)] public static extern bool MiniDumpWriteDump( IntPtr hProcess, uint processId, IntPtr hFile, uint dumpType, IntPtr exceptionParam, IntPtr userStreamParam, IntPtr callbackParam); } $processId 目标进程PID$processGet-Process-Id$processId$dumpPathD:\temp\totalcmd64.dmp$fileStreamNew-ObjectSystem.IO.FileStream($dumpPath,[System.IO.FileMode]::Create)# dumpType2 表示 MiniDumpWithFullMemory完整内存快照$result[MiniDumpHelper]::MiniDumpWriteDump($process.Handle,$processId,$fileStream.SafeFileHandle.DangerousGetHandle(),2,[IntPtr]::Zero,[IntPtr]::Zero,[IntPtr]::Zero)$fileStream.Close()Write-HostDump created:$result跑起来powershell-ExecutionPolicy Bypass-File dump.ps1看到Dump created: True快照到手。第二步请出 WinDbg 大夫加载 Dump.sympath srv*C:\Symbols*https://msdl.microsoft.com/download/symbols .open D:\temp\totalcmd64.dmp .reload符号服务器配好微软的 DLL 就都能解析出函数名了。第三步看看这是啥类型的 Dump.exr -1输出ExceptionAddress: 0000000000000000 ExceptionCode: 80000003 (Break instruction exception) ExceptionFlags: 00000000 NumberParameters: 080000003是断点异常——说明这是我们手动抓的快照不是崩溃。分析方向挂起/死锁。第四步翻主线程的调用栈破案关键切到主线程看看它到底卡在哪儿~0s k调用栈精简版从上到下是从表象到根源ntdll!NtWaitForSingleObject0x14 ← 卡在这儿死等一个内核对象 KERNELBASE!WaitForSingleObjectEx0x8e SHCore!SHCreateThread0x143 windows_storage!DataAccessCaches_InvalidateForLibrary0x274a ... shell32!SHELL32_IconCache_AboutToExtractIcons0x1df user32!DispatchMessageW0x741 user32!CreateWindowExW0x82 YunShellExtV1640xd8232 ← ★ 就是你百度网盘Shell扩展 YunShellExtV1640x1106c8 YunShellExtV164!DllGetClassObject0x69 ← ★ 初始化COM对象时出的事 YunShellExtV164!DllUnregisterServer0x57bc ntdll!LdrLoadDll0xfa KERNELBASE!LoadLibraryExW0x172 combase!CoCreateInstance0x14c ← 系统在创建COM实例 shell32!SHELL32_SHCreateDefaultContextMenu ← 系统在构建右键菜单 TOTALCMD640x20013e ← TC说我就想弹个右键菜单啊一眼看出来了百度网盘的 Shell 扩展在初始化时卡住了连累整个主线程一起躺平。第五步确认凶手身份lm m YunShellExtV164输出start end module name 00007ffc5db60000 00007ffc5ddf7000 YunShellExtV164 (export symbols) YunShellExtV164.dllYunShellExtV164“云”(Yun) ShellExt V1 64位→ 百度网盘的右键菜单扩展破案了。根因分析调用链还原TC: 我想弹个右键菜单shell32: 好嘞让我加载所有扩展COM: 来加载百度网盘扩展百度网盘: 等我初始化一下...百度网盘: 我要创建个窗口windows_storage: 帮我枚举一下存储信息SHCore: 开个线程干活你等着主线程: 等...等...等到天荒地老 ☠️来龙去脉Total Commander 在主线程上同步调用SHCreateDefaultContextMenu想弹个右键菜单系统乖乖地逐个加载所有注册的右键扩展轮到了百度网盘的YunShellExtV164.dll这哥们在初始化时搞了一堆骚操作创建窗口、枚举存储信息……最后开了个工作线程然后主线程傻等这个线程干完活然而那个线程似乎永远也干不完 → 主线程我等到花儿都谢了解决方案方案一打开百度网盘设置禁用 Shell 扩展推荐第一步打开百度网盘 → 点击右上角菜单按钮 → 选择「设置」第二步取消勾选在我的电脑显示网盘第三步在任务管理器中杀掉 Total Commander 进程重新启动即可恢复正常。方案二卸载百度网盘简单粗暴一了百了。如果你平时不怎么用百度网盘桌面端直接卸了清净。