某天正常关机,第二天开机提示:
无法登录到你的账户。通常可以通过从你的账户注销,然后重新登录来解决此问题。
注销重来,还是一样。进去是个临时桌面,文件和设置全没了。安全模式倒是能进。
网上搜到的办法基本都是去注册表 ProfileList 里改.bak。我照着改了不下五次,每次重启又变回去。前后折腾了两天,最后用 Procmon 抓了开机日志才找到原因:用户注册表文件NTUSER.DAT里一大片键直接没了。
环境
- 系统:Windows 版本 10.0.26200(Win11),Win10 思路一样
- 账户:微软账户登录
- 用户名:lenovo,下文路径都用这个,换成你自己的
原因
登录时系统要加载两个注册表文件:
C:\Users\用户名\NTUSER.DATC:\Users\用户名\AppData\Local\Microsoft\Windows\UsrClass.dat
第二个文件在哪,是从第一个文件里的User Shell Folders\Local AppData读出来的。我的NTUSER.DAT里这个键没了,系统找不到UsrClass.dat,重试几十次后放弃,给了一个临时配置文件,同时把 ProfileList 里对应的项改名成.bak。
所以改.bak只是把标记改回去,文件本身是坏的,下次登录照样失败。
走过的弯路
按时间顺序写。前两步对“只是 ProfileList 标记乱了”的情况是管用的,可以先试。
1. 退出安全模式
如果是在 msconfig 里勾了“安全引导”进的安全模式,之后每次开机都会进安全模式。取消:
Win + R→msconfig→ 引导 → 取消勾选“安全引导”- 或者管理员 cmd 执行:
bcdedit /deletevalue {current} safeboot2. 改 ProfileList
路径:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList找S-1-5-21-开头、ProfileImagePath指向你用户目录的项:
- 如果一个带
.bak、一个不带:删掉不带的(一般指向C:\Users\TEMP...),再把.bak去掉 - 把
RefCount和State改成 0
顺便说下State的值:0x100表示管理员账户,是正常的;0x8000是加载失败后系统打的标记。我看到的8100就是两者相加。S-1-5-18、19、20是系统账户,别动。
这里有两个坑:
- 不要在临时配置文件里改自己账户的这一项。注销时系统会重写 ProfileList,改了等于白改。要么进安全模式改,要么新建一个管理员账户进去改。
- 如果改完一重启,又冒出
.bak和一个新的不带后缀的项,说明问题不在标记,而是文件本身加载不了。别再反复改了,往下看。
3. 怀疑软件占用
事件查看器里 User Profile Service 报“无法加载注册表文件……正在使用备份”。网上说多半是杀毒软件占用了NTUSER.DAT。
我做了干净启动(msconfig → 服务 → 隐藏所有 Microsoft 服务 → 全部禁用),又用资源监视器搜ntuser的句柄,都没找到谁在占用。后来日志证明,跟软件没关系。
4. 移走事务日志
用户目录下有NTUSER.DAT{GUID}.TM.blf和.regtrans-ms这类文件,它们损坏也会导致加载失败。这些是隐藏 + 系统文件,资源管理器里不容易看到,用dir /a才能列出来:
dir /a C:\Users\lenovo\ntuser*移走:
mkdir C:\tm_backup attrib -h -s "C:\Users\lenovo\NTUSER.DAT{*" move "C:\Users\lenovo\NTUSER.DAT{*" C:\tm_backup\我这里移了也没用。
新建账户,用 Procmon 抓开机过程
新建一个管理员账户
在临时桌面里打开管理员 cmd:
net user fixer 123456 /add net localgroup administrators fixer /add第二行我这里报“指定的本地组不存在”,因为组名可能是中文。可以用 SID 来加,不受系统语言影响(管理员 PowerShell):
Add-LocalGroupMember -SID S-1-5-32-544 -Member fixer新账户能正常登录,说明系统本身没问题,出事的只是原账户的配置文件。后面所有操作都在 fixer 里做。
两个容易让人慌的现象,其实都正常:
- 刚建的账户在 ProfileList 里看不到,要第一次登录之后才会出现。
HKEY_USERS下只有当前已登录用户的项,所以看不到原账户。
Procmon 开机日志
Procmon 是微软 Sysinternals 的工具。步骤:
- 管理员运行 Procmon → Options → Enable Boot Logging,然后关掉 Procmon
- 重启,先登录原账户,让它失败一次,再注销
- 登录 fixer,打开 Procmon,提示保存开机日志时点 Yes
过滤条件我用的是:PID 选登录时那个 svchost(User Profile Service),Result 排除 SUCCESS,然后看出错时间前后的记录。
几个看着吓人、其实正常的结果:
FILE LOCKED WITH ONLY READERS/FILE LOCKED WITH WRITERS:系统账户加载自己的NTUSER.DAT时也是这样msedgewebview2.exe的RegLoadKey报PATH NOT FOUND:Hive Path 指向 fixer 自己的应用数据,跟原账户无关BUFFER OVERFLOW:只是缓冲区不够大,程序会换个大缓冲区再查一次
真正的线索是这样一段:
RegLoadKey加载C:\Users\lenovo\NTUSER.DAT,成功- 接着每隔大约 0.16 秒循环一次:打开
HKU\S-1-5-21-...-1001_Classes(NAME NOT FOUND)→ 读User Shell Folders\Local AppData→ 查AllowNonStandardUserProfilePaths策略。持续 8 秒,大约 50 次 - 整个过程中,没有任何一次对
UsrClass.dat的文件访问 - 最后
RegRenameKey把 ProfileList 里的项改名成.bak,State设为 32768(即 0x8000),然后开始创建 TEMP 配置文件
作为对比,同一份日志里正常账户查完那个策略,紧接着就去打开UsrClass.dat了。所以问题出在“找UsrClass.dat路径”这一步。
确认:NTUSER.DAT 坏了一大片
在 fixer 里,用 reg 命令把原账户的注册表挂上来看(管理员 cmd):
reg load HKU\test C:\Users\lenovo\NTUSER.DAT reg query HKU\test reg query "HKU\test\Software\Microsoft\Windows\CurrentVersion\Explorer" reg query "HKU\test\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" reg unload HKU\test我看到的结果:
- 顶层只剩
Software。正常应该有 AppEvents、Control Panel、Environment、Keyboard Layout 等十来个 Explorer下面只剩Advanced和FileExts两个子项,正常有几十个User Shell Folders:系统找不到指定的注册表项- 但
LogonCount是0x1bf,也就是 447 次。说明这确实是我用了很久的那个文件,不是加载错了
文件能加载,大小也正常(30 多 MB),内容却没了一大半。我的猜测是:关机时注册表正在写回磁盘,被打断了;下次加载时系统自动修复,把损坏的分支整块丢掉了。我当时 C 盘也快满了,可能有关系。这只是推测,没法证实。
查完一定要reg unload。不卸载的话这个文件一直被占用,原账户登录肯定失败。
怎么判断是不是同一个问题
- 改了
.bak,重启后又变回去 - 事件查看器 → Windows 日志 → 应用程序,来源 User Profile Service,有事件 1511(“找不到本地配置文件,正在用临时配置文件让你登录”)
- 用上面的
reg load去看,User Shell Folders不存在,或者顶层项明显少了一大截
三条都中,基本就是这个问题。缺的东西太多,手工补是补不全的,直接看下面的修复。
修复
方案 A:从卷影副本恢复(能保留全部设置)
前提是 C 盘开着系统保护。右键用户文件夹 → 属性 → 以前的版本,如果有出问题之前的版本,就可以试这个方案。
命令行做法(管理员 PowerShell)。先列出快照,选出问题之前最近的那个,把它挂成一个普通文件夹(编号换成你的,末尾的反斜杠不能少):
vssadmin list shadows cmd /c mklink /d C:\shadow \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy3\直接用 Copy-Item 复制会报拒绝访问,要用 robocopy 的备份模式/B:
robocopy "C:\shadow\Users\lenovo" "C:\ntuser_restore" NTUSER.DAT ntuser.dat.LOG1 ntuser.dat.LOG2 /B /COPY:DAT /R:0 /W:0之后的步骤:
- 先用
reg load检查复制出来的这份是好的 - 把当前的
NTUSER.DAT、ntuser.dat.LOG1、ntuser.dat.LOG2改名备份 - 放回旧版本,修好 ProfileList,重启
注意 LOG1、LOG2 要和 NTUSER.DAT 一起换。如果新文件配旧日志,系统会把旧日志回放到新文件上,可能又写坏。
我自己走了这条路,但是还是失败了,具体为什么没有查出来,发现失败之后已经崩溃了,直接去用了方案B。
方案 B:重建配置文件(我用的)
账户、密码、SID、已装的软件都不变,只是个人设置要重新弄。
- 只登录 fixer。用
quser确认原账户没在登录状态。 - 备份 ProfileList:
reg export "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList" C:\ProfileList_backup.reg- 把旧用户文件夹改名:
Rename-Item C:\Users\lenovo lenovo.old- 删掉原账户在 ProfileList 里的所有项。SID 换成你自己的,先列出来确认一遍再删:
$sid = "S-1-5-21-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-1001" $list = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList" Get-ChildItem $list | Where-Object { $_.PSChildName -like "$sid*" } # 确认列出来的都是原账户的,再执行删除 Get-ChildItem $list | Where-Object { $_.PSChildName -like "$sid*" } | Remove-Item -Recurse- 重启,登录原账户。PIN 大概率用不了,点“登录选项”改用密码。系统会重新生成一个干净的
C:\Users\lenovo。
重建之后的几个坑
微软账户首次登录:“哎呀,出错了……有可能是我们的错误”
这个提示如果出现在“欢迎 / 正在为你设置”之后,说明密码已经验证过了,卡在首次登录的联网设置上,比如 PIN。
先试断网:在登录界面关掉 Wi-Fi,用密码登录。(我这个报错不知道为什么,过了一会自动就好了)
还不行的话,在 fixer 里加几条策略,跳过首次登录的设置流程:
reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" /v EnableFirstLogonAnimation /t REG_DWORD /d 0 /f reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\OOBE" /v DisablePrivacyExperience /t REG_DWORD /d 1 /f reg add "HKLM\SOFTWARE\Policies\Microsoft\PassportForWork" /v Enabled /t REG_DWORD /d 0 /f reg add "HKLM\SOFTWARE\Policies\Microsoft\PassportForWork" /v DisablePostLogonProvisioning /t REG_DWORD /d 1 /f再把 PIN 的存储文件夹重置一下(会清掉这台电脑上所有账户的 PIN):
$ngc = "C:\Windows\ServiceProfiles\LocalService\AppData\Local\Microsoft\Ngc" takeown /f $ngc /r /d y | Out-Null icacls $ngc /grant administrators:F /t | Out-Null Rename-Item $ngc "Ngc.old"登录成功以后,把 PassportForWork 这条删掉,不然设置里没法重新添加 PIN:
reg delete "HKLM\SOFTWARE\Policies\Microsoft\PassportForWork" /f迁移数据
常用文件夹直接用 robocopy 复制过去。/XJ用来跳过系统自带的 junction(My Music这类“快捷方式文件夹”),不加的话可能陷入死循环:
$old = "C:\Users\lenovo.old" $new = "C:\Users\lenovo" foreach ($f in "Desktop","Documents","Downloads","Pictures","Videos","Music","Favorites") { robocopy "$old\$f" "$new\$f" /E /COPY:DAT /XJ /R:1 /W:1 /MT:16 }用户目录下的其他东西,比如自己建的文件夹、.ssh、.gitconfig、anaconda3,也要记得搬。因为新目录名和原来一样,路径不变,大部分东西搬过来就能直接用。
AppData 可以搬,但下面这几个不要搬:
| 不要搬 | 原因 |
|---|---|
NTUSER.DAT*、ntuser.ini | 就是坏掉的那个注册表 |
Local\Microsoft\Windows | UsrClass.dat在这里面 |
Local\Packages | 应用商店应用的数据,跟应用注册信息绑定,搬过来可能导致开始菜单和设置打不开 |
Local\Temp | 临时文件,没用 |
还有一个小技巧:Roaming\Microsoft\Protect里存着加密用的密钥,把它“只补不覆盖”地复制过去:
robocopy "$old\AppData\Roaming\Microsoft\Protect" "$new\AppData\Roaming\Microsoft\Protect" /E /COPY:DAT /XC /XN /XO /XJ只要登录密码没改过,浏览器里保存的密码就还能解密,省得一个个重新登录。
C 盘满了:同一个盘要用移动,不要复制
lenovo.old和lenovo在同一个盘上,复制就等于存了两份,我复制 AppData 复制到一半 C 盘就快满了。
同一个盘里用Move-Item只是改一下位置,瞬间完成,不占额外空间。目标位置已经复制过一部分的,用robocopy /MOVE把剩下的补齐,它每移完一个文件就删掉源文件。
# 目标不存在:直接移动 Move-Item "$old\AppData\Roaming\某软件" "$new\AppData\Roaming\某软件" # 目标已存在:补齐剩下的文件并删除源文件 robocopy "$old\AppData\Roaming\某软件" "$new\AppData\Roaming\某软件" /E /MOVE /XJ /R:1 /W:1C 盘快满时别硬着头皮继续写。没空间写注册表的时候,新的配置文件也可能被写坏。
删除旧目录:别用 Remove-Item -Recurse
lenovo.old里有Application Data、My Documents这类 junction,它们指向的是C:\Users\lenovo\...,而这个路径现在就是新的配置文件。PowerShell 5.1 的Remove-Item -Recurse、不带/skipsl的takeown /r、不带/l的icacls /t,都有可能顺着 junction 走进新目录,把里面的东西删掉或者把权限改乱。
用 cmd 的 rmdir,它只删 junction 本身,不会进去:
cmd /c rmdir /s /q "C:\Users\lenovo.old"如果有删不掉的文件,先跑下面两条,再执行一次 rmdir:
takeown /f "C:\Users\lenovo.old" /r /d y /skipsl icacls "C:\Users\lenovo.old" /grant administrators:F /t /l旧目录和 fixer 账户建议先留一周,确认东西都齐了再删。
最后
回头看,排查顺序可以是这样:
- 先按常规方法改
.bak。改完重启又变回去,就别再改了 - 新建一个管理员账户,用
reg load看看原账户的NTUSER.DAT里还剩什么 - 内容缺失的话,有快照就恢复,没有就重建配置文件
- 想弄清楚到底卡在哪一步,Procmon 开机日志最直接
以后注意三件事:C 盘至少留 15~20 GB 空间;开着系统保护,出事时还能从“以前的版本”里捞东西;系统在更新或关机时,别长按电源键强制关机。
我前后两天,大部分时间都耗在了反复改.bak上。早点建个新账户去看看NTUSER.DAT里还剩什么,能省不少事。