Total Commander 主线程卡死问题排查——百度网盘 Shell 扩展:你搁这等啥呢?
Total Commander 主线程卡死问题排查
问题现象
某天正愉快地用 Total Commander(64位)管理文件,右键一点……好家伙,整个界面直接石化,鼠标转圈圈,窗口标题栏写着大大的"未响应"。只能含泪打开任务管理器把它送走。
用 PowerShell 确认一下,果然凉了:
Get-Process -Name "TOTALCMD64" | Select-Object Id, ProcessName, Responding
输出:
Id ProcessName Responding
-- ----------- ----------
1234 TOTALCMD64 False
Responding = False,实锤了——主线程消息循环彻底罢工。
排查工具
| 工具 | 干啥用的 |
|---|---|
| PowerShell | 确认进程状态、生成 dump 文件 |
| WinDbg | 打开 dump 文件,翻线程调用栈找"凶手" |
| dbghelp.dll | 提供 MiniDumpWriteDump API,用来给进程"拍快照" |
排查步骤
第一步:给卡死的进程拍个"遗照"(生成 Dump)
进程卡死了但没崩,系统不会自动生成 dump,得我们自己动手。
写个 PowerShell 脚本 dump.ps1:
Add-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>
$process = Get-Process -Id $processId
$dumpPath = "D:\temp\totalcmd64.dmp"
$fileStream = New-Object System.IO.FileStream($dumpPath, [System.IO.FileMode]::Create)
# dumpType=2 表示 MiniDumpWithFullMemory(完整内存快照)
$result = [MiniDumpHelper]::MiniDumpWriteDump(
$process.Handle, $processId,
$fileStream.SafeFileHandle.DangerousGetHandle(),
2, [IntPtr]::Zero, [IntPtr]::Zero, [IntPtr]::Zero)
$fileStream.Close()
Write-Host "Dump 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: 0
80000003 是断点异常——说明这是我们手动抓的快照,不是崩溃。分析方向:挂起/死锁。
第四步:翻主线程的调用栈(破案关键)
切到主线程,看看它到底卡在哪儿:
~0s
k
调用栈(精简版,从上到下是从"表象"到"根源"):
ntdll!NtWaitForSingleObject+0x14 ← 卡在这儿:死等一个内核对象
KERNELBASE!WaitForSingleObjectEx+0x8e
SHCore!SHCreateThread+0x143
windows_storage!DataAccessCaches_InvalidateForLibrary+0x274a
...
shell32!SHELL32_IconCache_AboutToExtractIcons+0x1df
user32!DispatchMessageW+0x741
user32!CreateWindowExW+0x82
YunShellExtV164+0xd8232 ← ★ 就是你!百度网盘Shell扩展
YunShellExtV164+0x1106c8
YunShellExtV164!DllGetClassObject+0x69 ← ★ 初始化COM对象时出的事
YunShellExtV164!DllUnregisterServer+0x57bc
ntdll!LdrLoadDll+0xfa
KERNELBASE!LoadLibraryExW+0x172
combase!CoCreateInstance+0x14c ← 系统在创建COM实例
shell32!SHELL32_SHCreateDefaultContextMenu ← 系统在构建右键菜单
TOTALCMD64+0x20013e ← TC说:我就想弹个右键菜单啊!
一眼看出来了:百度网盘的 Shell 扩展在初始化时卡住了,连累整个主线程一起躺平。
第五步:确认"凶手"身份
lm m YunShellExtV164
输出:
start end module name
00007ffc`5db60000 00007ffc`5ddf7000 YunShellExtV164 (export symbols) YunShellExtV164.dll
YunShellExtV164 = “云”(Yun) + ShellExt + V1 + 64位 → 百度网盘的右键菜单扩展,破案了。
根因分析
调用链还原
来龙去脉
- Total Commander 在主线程上同步调用
SHCreateDefaultContextMenu想弹个右键菜单 - 系统乖乖地逐个加载所有注册的右键扩展,轮到了百度网盘的
YunShellExtV164.dll - 这哥们在初始化时搞了一堆骚操作:创建窗口、枚举存储信息……
- 最后开了个工作线程,然后主线程傻等这个线程干完活
- 然而那个线程似乎永远也干不完 → 主线程:???我等到花儿都谢了
解决方案
方案一:打开百度网盘设置,禁用 Shell 扩展(推荐)
第一步:打开百度网盘 → 点击右上角菜单按钮 → 选择「设置」

第二步:取消勾选"在我的电脑显示网盘"

第三步:在任务管理器中杀掉 Total Commander 进程,重新启动即可恢复正常。
方案二:卸载百度网盘
简单粗暴,一了百了。如果你平时不怎么用百度网盘桌面端,直接卸了清净。

472

被折叠的 条评论
为什么被折叠?



