追查 AppData\LocalLow 里的"乱码文件":一场从文件头 INSC 开始的溯源
现象:
C:\Users\<用户>\AppData\LocalLow根目录下不断冒出名字像乱码、没有扩展名的文件,删了还会再长出来。结论:它们是 Intel 核显驱动的着色器缓存(Shader Cache) ,文件名是 64 位十六进制的缓存哈希,文件头魔数
INSC就是 I ntel S hader C ache。不是病毒,不是乱码。排查机器:机械革命(MECHREVO)YAOSHI 系列,Intel Arrow Lake + NVIDIA RTX 5070 Ti Laptop,Intel 核显驱动 32.0.101.6629。
一、结论
| 问题 | 答案 |
|---|---|
| 这些文件是什么? | Intel 显卡驱动的着色器缓存条目 |
| 文件名为什么像乱码? | 它是缓存内容的哈希值(64 个十六进制字符),本来就没有扩展名 |
文件头 INSC 是什么? |
Intel Shader Cache 的魔数,在 Intel 自己的驱动 DLL 里能搜到 |
| 是病毒吗? | 不是。所有者是当前用户,属性是 Archive + NotContentIndexed,内容是纯二进制 |
| 能删吗? | 能。实测 19 个文件全部未被占用;删掉只影响首次加载时的着色器编译速度 |
| 为什么删了还会回来? | 只要 Intel 核显还在参与渲染,驱动就会重新写 |
| 怎么根治? | 切"独显直连"(MUX),让核显不参与渲染 |
基本上就是intel 核显驱动不知道出了什么bug,把着色器缓存文件写错位置了。也可以直接右键文件属性把所有乱码文件设为隐藏,眼不见心不烦。
注意 :网上那个"LocalLow 出现乱码文件"的帖子里,被标记为答案的建议是执行 rd /s /q %USERPROFILE%\AppData\LocalLow\。千万别照做 ------LocalLow 里躺着几十个游戏的存档目录。那个帖子的评论区就有人照做之后,游戏进度全没了、恢复不了。
二、乱码文件
如下图,就是这些数字字母文件名,没有后缀,实际上并不是乱码,应该是某种id 或者hash。

所有文件的内容特征都是以INSC 开头,后面跟一段疑似是日期的文本,之后就全是乱码,显然文件本身应该是某种二进制格式。

用INSC 前缀在LocalLow 下搜索,一共87 个文件,分布在两个位置:
| 位置 | 数量 | 体积(扫描时刻) |
|---|---|---|
LocalLow\(根目录,就是"乱码文件"所在处) |
19 | 99,716 字节(约 97 KB) |
LocalLow\Intel\ShaderCache\ |
68 | 1,507,576 字节(约 1.4 MB) |
注:
Intel\ShaderCache是活的------驱动随时在写。我前后两次测量同一个目录,字节总数从 1,501,107 变成 1,507,576,因为有些 26 字节的空壳在中间被填上了载荷。数量稳定,体积会漂移。
两个位置的文件名重合 0 个 ------所以根目录那批不是Shader 下面文件的副本或残留,而是各自独立写出来的条目。这也是第一个强信号:LocalLow\Intel\ShaderCache 是 Intel 的"正规"目录,而根目录那批是跑错了地方。
三、INSC 是什么?去驱动二进制里找答案
猜测没有意义,直接验证。我把文件头按字节拆开看:
=== LocalLow\ed8b7e4b...c1d97 (38,706 字节) ===
0 49 4e 53 43 67 7d 06 00 INSCg}..
8 00 02 00 46 65 62 31 38 ...Feb18
16 32 30 32 35 32 30 32 39 20252029
24 34 35 cb a9 06 76 ee 4a 45...v.J
32 15 ed fb a1 95 7a 2d c7 .....z-.
40 ae b2 10 42 a0 18 c3 84 ...B....
肉眼就能读出两段东西:魔数 INSC,以及 ASCII 字符串 Feb182025202945。这明显是一个编译器构建时间戳 (__DATE__/__TIME__ 风格),即 2025-02-18 20:29:45。
那么问题变成:哪一家的代码是 2025 年 2 月 18 日构建的?
看一眼显卡:
powershell
Get-CimInstance Win32_VideoController | Select-Object Name, DriverVersion, DriverDate
Name : NVIDIA GeForce RTX 5070 Ti Laptop GPU
DriverVersion : 32.0.16.1714
DriverDate : 2026/9/17
Name : Intel(R) Graphics
DriverVersion : 32.0.101.6629
DriverDate : 2025/2/18 ← 对上了
Intel 核显驱动的日期正是 2025/2/18 ,与文件头里的构建戳同一天。
接下来是决定性的一步:在 Intel 自己的驱动二进制里搜 INSC 。驱动 UMD(User Mode Driver)位于 C:\Windows\System32\DriverStore\FileRepository\:
powershell
$dir = 'C:\WINDOWS\System32\DriverStore\FileRepository\iigd_dch.inf_amd64_9fadbfb5f574c7eb'
Get-ChildItem -LiteralPath $dir -File -Include 'ig*.dll' |
ForEach-Object {
$txt = [System.Text.Encoding]::ASCII.GetString([System.IO.File]::ReadAllBytes($_.FullName))
if ($txt.Contains('INSC')) { "{0} v{1}" -f $_.Name, $_.VersionInfo.FileVersion }
}
结果 17 个 Intel 驱动组件里都有这个魔数 ,且版本号全部是 32.0.101.6629:
igd10um64xe.dll D3D10/11 UMD
igd12um64xe2.dll D3D12 UMD
igd12um64xeh.dll D3D12 UMD (Xe-HPG)
igd12um64xel.dll D3D12 UMD (Xe-LPG)
igd9trinity64.dll Trinity 世代 UMD
igvk64.dll Vulkan ICD
igxelpgicd64.dll OpenGL ICD
npu_level_zero_umd.dll Intel NPU UMD
...(另有 9 个 32 位版本)
但这还不是铁证 ------"某个字符串出现在 DLL 里"和"这个 DLL 写这种文件"是两回事。真正的铁证来自构建戳逐字比对:
| 组件 | 构建戳 |
|---|---|
64 位驱动 DLL(igd10um64xe / igd12um64xe2 / igvk64 / igxelpgicd64 ...) |
Feb182025202945 |
32 位驱动 DLL(igd10um32xe / igd12um32xe2 ...) |
Feb182025201453 |
LocalLow 根目录 19 个文件 |
Feb182025202945(19/19) |
Intel\ShaderCache 68 个文件 |
Feb182025202945(66 个)+ Feb182025201453(2 个) |
文件里嵌的构建戳与 64 位驱动 DLL 的构建戳完全相同 ,而 32 位 DLL 是另一个戳------这直接锁定了写入者:Intel 的 64 位用户态显卡驱动 。(Intel\ShaderCache 里那两个 ...1453 的文件,则是 32 位驱动组件写的,说明同一个目录会收纳两种位宽的条目。)
最后,把 DLL 里的 UTF-16 字符串捞出来,答案就写在 Intel 自己脸上:
Intel Shader Cache Command Queue Prrocessing Thread ← 注意 Intel 自己的拼写错误 "Prrocessing"
\Intel\ShaderCache
ShaderCacheForceDisabled
OfflineShaderCacheHarvestTargetDirectory
INSC = Intel Shader Cache,旁证齐全到不需要再猜。
四、排除"某个游戏写坏了"的可能
时间戳交叉比对 :对根目录每个文件,找出前后 3 分钟内 LocalLow 下其他文件的写入活动:
powershell
$root = Get-ChildItem -LiteralPath $ll -File -Force
$others = Get-ChildItem -LiteralPath $ll -Recurse -Force -File -ErrorAction SilentlyContinue |
Where-Object { $_.DirectoryName -notlike "$ll" -and $_.DirectoryName -notlike "*\Intel*" }
foreach ($f in $root) {
$near = $others | Where-Object { [math]::Abs(($_.LastWriteTime - $f.LastWriteTime).TotalSeconds) -lt 180 }
"{0} {1} -> {2} 个同期文件" -f $f.LastWriteTime, $f.Name.Substring(0,16), $near.Count
}
结果:19 个文件里没有一次与游戏存档目录的写入时间重合 (只匹配到 Microsoft\CryptnetUrlCache 这种系统证书缓存的噪音)。也就是说,这些文件是驱动自己的后台线程写的,跟游戏进程无关。
占用测试:确认它们是不是像网上说的"无法删除":
powershell
$root | ForEach-Object {
try { $fs = [System.IO.File]::Open($_.FullName,'Open','Write','None'); $fs.Close(); "FREE $($_.Name)" }
catch { "LOCKED $($_.Name)" }
}
根目录那 19 个:19/19 全部 FREE(可以独占打开),随时可以删。
但同样的测试打到 Intel\ShaderCache 时,出现了本次排查最直观的一幕------有 4 个文件直接被拒绝访问:
Exception calling "OpenRead": "The process cannot access the file
'...\Intel\ShaderCache\121f266ebbe7bcb5...' because it is being used by another process."
挨个验证这 4 个文件,改用 FileShare.ReadWrite 才能读进去(注意 Length 取自目录列表,不需要打开文件):
powershell
$fs = [System.IO.File]::Open($p, 'Open', 'Read', 'ReadWrite') # 允许共享读写
结果 4 个全都是合法的 INSC 文件 (驱动戳 Feb182025202945),长度分别是 195,042 / 99,311 / 26 / 26 字节。
这就是"这些文件删不掉"的真相 :不是权限问题,也不是病毒锁文件,而是驱动此刻正开着它们 。缓存目录里的文件处于滚动占用状态------刚才测前 5 个是 FREE,回头看就发现 4 个被占住了。重启(或让驱动释放句柄)之后即可删除,这也解释了为什么微软 Q&A 里有人说"无法删除、还会持续增加"。
那么到底是谁在写?看看谁加载了 Intel 的驱动:
powershell
Get-Process | ForEach-Object {
try { $m = $_.Modules | Where-Object { $_.ModuleName -match '^(igd1[02]um|igvk|igxelpgicd|igd9trinity)' }
if ($m) { "{0,-28} PID {1,-7} {2}" -f $_.ProcessName, $_.Id, $m[0].ModuleName } } catch {}
}
本机当时的输出(10 个进程):
EpicGamesLauncher PID 33796 igd10umt64xe.DLL
explorer PID 21996 igd10umt64xe.DLL
LockApp PID 2868 igd10umt64xe.DLL
PowerToys.ColorPickerUI PID 17292 igd9trinity64.dll
PowerToys.QuickAccess PID 17204 igd10umt64xe.DLL
PowerToys.ShortcutGuide PID 17340 igd10umt64xe.DLL
RuntimeBroker PID 33264 igd10umt64xe.DLL
SearchHost PID 13720 igd10umt64xe.DLL
StartMenuExperienceHost PID 6032 igd10umt64xe.DLL
TextInputHost PID 34152 igd10umt64xe.DLL
这份名单彻底解释了行为特征:写缓存的不是某个游戏,而是任何在 Intel 核显上渲染的进程 ------桌面 explorer、开始菜单、搜索、锁屏、输入法候选窗、PowerToys 都在列。这就解释了为什么:
- 你不打游戏的时候这些文件也会增加;
- 你删掉之后它们很快又回来(桌面上随便点几下就有新的着色器要编译);
- 数量是慢慢涨而不是一次爆发(每次出现新着色器组合才会写一条)。
五、为什么会跑到 LocalLow 根目录
正常位置是 LocalLow\Intel\ShaderCache\,那 19 个为什么会落在上一层?
在驱动 DLL 里能读到一条相对路径字符串:
.\Intel\ShaderCache
同时还有 SHGetKnownFolderPath(读取系统"已知文件夹"API)。合理推断是:缓存路径 = 已知文件夹基准路径 + 相对子路径 拼接而成;当 Intel 子目录的解析或创建失败时,条目就退化落到了基准目录本身,也就是 LocalLow 根。驱动里还带着 \\?\ 长路径前缀和相关错误字符串(Failed creating read operation、Failed to write the file.、Error opening file:、Cache file header corrupted!),也印证了这条写盘路径上有失败分支。
不过具体的bug 逻辑就没必要追查进去了,反正就算知道了也没用。
时间线指向驱动/系统更新这个诱因:
| 时间 | 事件 |
|---|---|
| 2026-10-06 00:14:01 | LocalLow\Microsoft 目录重建 |
| 2026-10-06 00:18:36 | LocalLow\Intel 目录创建,同时出现第一批根目录文件 |
| 2026-10-06 00:30:18 | LocalLow\NVIDIA 目录重建 |
| 2026-10-06 | Intel(R) Icls 组件安装(安装日期 20261006) |
| 2026-10-06 00:18 ~ 00:37 | 根目录文件爆发式出现(14 个) |
| 2026-10-07 ~ 10-10 | 零星增加(00:01 / 00:54 / 19:35 / 01:40 各一批) |
一次显卡驱动/系统更新之后开始出现,之后零星增长------完全符合缓存的行为特征。另外 Intel\ShaderCache 一直在活跃更新(最近一个文件是 10/10 23:56),说明缓存机制本身工作正常,只是部分条目写错了位置。
六、INSC 文件格式备忘
把 87 个文件的结构总结如下(offset 从 0 开始):
| 偏移 | 长度 | 内容 |
|---|---|---|
| 0 | 4 | 魔数 INSC(49 4E 53 43) |
| 4 | 7 | 版本/标志位。有内容的条目为 67 7d 06 00 00 02 00;26 字节空壳全为 00 |
| 11 | 15 | 驱动构建时间戳 ,ASCII,格式 Mmm<dd><yyyy><hh><mm><ss>,实测 Feb182025202945 = 2025-02-18 20:29:45 |
| 26 | 16 | 缓存键(哈希/类 UUID),每个文件都不同 |
| 42 | 变长 | 编译后的着色器数据块 |
两个有意思的观察:
- 26 字节的文件占了整整 44 个(共 87 个)------它们只写了头部、没有任何载荷,是"空壳"条目。
- 体积分布极度长尾:最小的 26 字节,最大 656,842 字节;根目录那 19 个总共不到 100 KB。
对照属性也能佐证这是驱动缓存:
Attributes = Archive, NotContentIndexed
NotContentIndexed(不被 Windows 搜索索引)是驱动缓存的典型属性------系统自己也知道这类文件不该进索引。
七、怎么处置
方案 1:不治本但安全(定期清理)
只删 LocalLow 根目录 里"64 位十六进制 + 无扩展名"的文件,绝不碰任何子目录:
powershell
$ll = Join-Path $env:USERPROFILE 'AppData\LocalLow'
Get-ChildItem -LiteralPath $ll -File -Force |
Where-Object { $_.Name -match '^[0-9a-f]{64}$' } |
ForEach-Object {
# 双保险:确认魔数真的是 INSC 才删;被占用的文件跳过,下次再清
try {
$fs = [System.IO.File]::Open($_.FullName, 'Open', 'Read', 'ReadWrite')
$b = New-Object byte[] 4; $fs.Read($b,0,4) | Out-Null; $fs.Close()
if ([System.Text.Encoding]::ASCII.GetString($b) -eq 'INSC') { Remove-Item -LiteralPath $_.FullName -Force }
} catch { Write-Warning ("跳过(被占用):" + $_.Name) }
}
实测这段的匹配逻辑在本机精确命中 19 个文件 / 99,716 字节,且不触碰任何目录(我实测时只做了统计,没有真的执行删除)。
代价:下次进游戏要重新编译着色器,首次加载会略卡一下。不影响任何存档。
方案 2:根治(推荐)
用笔记本自带的控制中心(本机是"机械革命控制中心")切换独显直连(MUX)。核显不参与渲染后,Intel 驱动就不会再生成这些缓存。
注意:切换前先确认外接显示器接在哪块显卡的输出上(本机同时接了内置 BOE 面板和外接显示器),避免切完外接屏没信号。
方案 3:驱动注册表开关(不建议)
驱动里存在这个值名:
HKLM\SOFTWARE\Intel\Display\igfxcui\3D\ShaderCacheForceDisabled
本机不存在 该键(即处于驱动默认状态)。理论上置 1 可禁用着色器缓存,但代价是每次运行都要重新编译全部着色器,游戏卡顿会明显很多。除非你完全无法忍受这些文件,否则不建议。
方案4:眼不见心不烦
要是担心删了会影响什么,就直接右键文件属性把"隐藏"勾上。

八、⚠️ 反面教材:那条被标记为"答案"的删除命令
在 微软 Q&A 的"locallow 文件夹里出现大量乱码文件" 帖子里,答复给出的"根治方法"是:
cmd
rd /s /q %USERPROFILE%\AppData\LocalLow\
这是一条会毁掉游戏存档 的命令。LocalLow 不是缓存目录,它是 Unity 等引擎存放用户数据 的标准位置------存档、配置、进度全在里面。本机 LocalLow 下有 60 多个游戏目录,那个帖子的评论区里,就有用户执行后留言:"把我游戏数据全删除了,还恢复不了,我真无语了啊"。
正确的做法是:只按文件名模式和魔数精确匹配、只删根目录的那几个文件。 一个简单的判别规则:
名字是 64 个十六进制字符、没有扩展名、文件头是
INSC→ 驱动缓存,可删。名字是目录、里面有
.json/.dat/.sav/.es3之类 → 游戏数据,别碰。
关于"着色器缓存能不能删",微软 Q&A 的另一条 回答 也确认:LocalLow\Intel\ShaderCache 里是临时的编译着色器数据,删除是安全的。
附:一行自查脚本
不确定自己机器上 LocalLow 里的可疑文件是不是同一类?跑这个:
powershell
$ll = Join-Path $env:USERPROFILE 'AppData\LocalLow'
Get-ChildItem -LiteralPath $ll -Recurse -Force -File -ErrorAction SilentlyContinue | ForEach-Object {
try {
# FileShare.ReadWrite:避免漏掉正被驱动占用的文件
$fs = [System.IO.File]::Open($_.FullName, 'Open', 'Read', 'ReadWrite')
$b = New-Object byte[] 26; $n = $fs.Read($b,0,26); $fs.Close()
# 用 -ge 4 而不是 -eq 26:即使只读回部分字节也不漏判(见方法论第 7 条)
if ($n -ge 4 -and [System.Text.Encoding]::ASCII.GetString($b,0,4) -eq 'INSC') {
[pscustomobject]@{
路径 = $_.FullName
大小 = $_.Length
驱动戳 = if ($n -ge 26) { [System.Text.Encoding]::ASCII.GetString($b,11,15) } else { '<短文件>' }
修改 = $_.LastWriteTime
}
}
} catch {}
} | Format-Table -AutoSize
如果 驱动戳 显示 Feb182025202945 或类似 Mmm<dd><yyyy><hh><mm><ss> 的字符串,就说明你遇到的和我这次是同一回事。
排查环境:Windows 11 · Intel® Graphics 32.0.101.6629 · NVIDIA GeForce RTX 5070 Ti Laptop GPU · MECHREVO YAOSHI Series (Arrow Lake)