前言
目前我把游戏分别放在本地D:\game和NAS的G:\game(映射盘符)上运行(主要是gal和一些SLG太占空间了,又不想删)。长时间后,Local,Roaming,LocalLow 里会有各种游戏生成的存档和配置文件目录。删游戏时这些目录并不会自动消失,AppData 越来越臃肿,想手动清理又怕删错,备份更是无从下手
于是我写了一套 PowerShell 脚本:实时监控文件夹创建,自动记录游戏路径和存档位置,并在确认后将存档迁移到统一目录,在原位置留下符号链接。这样既能把存档集中管理,又能让 AppData 保持干净。不过,NAS 映射盘符是整个过程里最大的坑(但大多佬们似乎用不到)。本文将分享我从“映射失败”到“稳定挂载”的全过程,以及脚本在中文转码、路径匹配、去重、队列管理等方面踩过的坑和最终方案。
而且我现在的环境很特殊:NAS 和主机用网线直连,主机通过 ICS 让 NAS 共享校园网。下一篇博客会补充 NAS 实战中的更多内容(为此我花了一周在学习网络通信协议)。
手动查找并迁移已有文件
1. 按修改时间查找文件
如果知道文件大概的修改时间范围,可以用以下命令快速定位:
Get-ChildItem -Path "D:\game" -Recurse -File | Where-Object {
$_.LastWriteTime -ge "2026-06-01 10:40" -and $_.LastWriteTime -le "2026-06-01 11:00"
}
找到后根据完整路径判断属于哪个游戏,然后手动复制存档到备份目录(例如 D:\GameSaves\manual)。
2. 批量迁移脚本(BAT 示例)
对于大量已知映射关系的配置文件,可以写一个批处理脚本。注意:BAT 脚本如需输出中文,必须保存为 ANSI(GBK) 编码;而给 AI 或代码库看的脚本建议用 UTF-8。
@echo off
set SRC1=C:\Users\admin\AppData\Local\GameA\Save
set DST1=D:\GameSaves\GameA
xcopy "%SRC1%" "%DST1%" /E /I /Y
set SRC2=C:\Users\admin\AppData\LocalLow\GameB
set DST2=D:\GameSaves\GameB
xcopy "%SRC2%" "%DST2%" /E /I /Y
echo 迁移完成
pause
NAS 盘符映射
1. 在 Windows 中映射 NAS 文件夹
我的 NAS 型号是绿联 Dxp4800plus,通过 ICS 共享网络,设置的私网IP 为 192.168.137.20。我把所有游戏放在 NAS 共享文件夹ACG(原名acg资源,后来改名)下,并映射到主机的 G: 盘。
正确映射方法(一定要勾选“登录时重新连接”):
- 右键“此电脑” → “映射网络驱动器”。
- 驱动器选择
G:,文件夹选择NAS设备\ACG - 必须勾选"登录时重新连接",不然后面开机自启会出问题。
用校园网连接NAS时,在
网络可能会找不到设备,需要先进入WLAN把校园网从专用切换为公用,再在网络里重新转为专用,才能发现 NAS 设备。我现在也没搞清楚根本原因是什么,如果佬们知道正确的修改方法请告诉我。
2. 几个踩坑点
踩坑 1:修改共享名称后映射失效当我把共享文件夹从acg资源改名为ACG后,就无法进入之前映射好的G:盘了。这是因为映射驱动器指向的远程路径是 \\...\acg资源,而实际共享已不存在。
解决方法:
- 先删除旧映射G盘
- 按照上述步骤重新映射到新文件夹
ACG
踩坑 2:到底该用盘符(G:)还是 UNC 路径(\IP\share)?一旦修改 NAS 共享名,必须同时更新所有客户端的映射,并更新脚本中的路径
这是困扰我最久的问题(主要是不停打开游戏和脚本测试,还要不断删除对应的文件和json内容)。
脚本需要匹配运行中游戏的可执行文件路径,而 Get-Process 返回的 Path 属性在不同启动方式下表现不一致:
- 如果通过资源管理器双击
G:\game\xxx.exe启动,进程路径有时是G:\game\...(盘符形式)。 - 如果通过
\\192.168.137.20\ACG\game\xxx.exe直接启动,进程路径是 UNC。 - 有些游戏启动器可能会强制转换路径。
我最初按 UNC 路径\\192.168.137.20\ACG\game设置$gameRoot,但实际运行时却匹配不到(因为进程路径是G:\game开头)。后来改为G:\game就成功了,所以最稳妥的做法是把盘符和UNC都配置上,让脚本自己去匹配。
踩坑 3:开机自启时 G 盘还未连上不知道为什么,在
powershell中cd \\192.168.137.20\ACG\game却没有问题
设置任务计划程序开机启动脚本后,发现脚本虽然运行了,但始终检测不到 NAS 上的游戏。日志显示 [注意] 未检测到游戏进程。
原因:用户登录后,系统需要几秒钟来恢复网络驱动器。而脚本在登录瞬间就执行了,此时 G: 盘还不存在。
解决方案:在任务计划程序的触发器设置中,添加 “延迟任务时间 30 秒”(或更长,如 60 秒),这样脚本会等待网络和映射完全准备好再启动。
实现自动化监控脚本
核心需求:
- 监控三个存档常用目录:
%LOCALAPPDATA%、%APPDATA%、%USERPROFILE%\AppData\LocalLow(即Local,Roaming,LocalLow) - 当有新文件夹被创建(某个游戏第一次生成存档)时,自动记录
- 同时检查本地
D:\game和 NAS 映射的G:\game路径,检测当前运行的游戏进程并将其 exe 路径以 Base64 存入队列
1. 设置 PowerShell 执行策略
首次运行脚本前,需要允许执行本地脚本:
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
2. 监控脚本(Watch-GameSaves.ps1)
以下为脚本核心结构(完整代码略去,仅说明逻辑):
- 定义监控根目录、排除文件夹列表。
- 使用
FileSystemWatcher监视$watchPaths下的文件夹创建事件。 - 事件触发后:
- 跳过已存在的连接点或排除文件夹。
- 延迟 3 秒,给游戏时间完成写入。
- 获取正在运行的进程,匹配路径是否以
D:\game或G:\game开头。 - 将匹配到的第一个游戏 exe 路径转为 Base64(避免 JSON 中的转义和乱码问题)。
- 将存档路径、游戏 exe Base64、时间等信息写入
pending.json。
3. 解决中文乱码:Base64 转码
因为游戏路径中可能出现中文(如“除灵猎人”),直接存储到 JSON 会导致编码混乱(而且很难解决,不论将文件保存为UTF-8还是GBK都不行,因为本质是在action中进行的解码)。解决方法是将 exe 路径进行 Base64 编码:
{
"srcPath": "C:\\Users\\admin\\AppData\\Local\\NebelTR",
"time": "2026-06-04 15:28:26",
"gameExeBase64": "RDpcZ2FtZVxSUEdcQkJR5aSn5aW944GNXOmZpOeBteeMjuS6ulzpmaTngbXnjI7kurotQ04tMS4xMlxHYW1lLmV4ZQ==",
"dirName": "NebelTR",
"remark": ""
}
使用时通过 [System.Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($base64)) 解码即可得到原始中文路径。
4. 避免重复记录已处理目录
某个存档目录已经成功迁移并创建了符号链接后,之后游戏再次运行,监控脚本又检测到同一目录的“创建”事件,就会导致重复记录。
解决方法:在向pending.json追加新条目之前,先检查队列中是否已存在相同的srcPath。若有,直接跳过,不重复添加。这样即使链接目录被误触创建事件,也不会污染队列,同时也避免了后续转移脚本重复处理。
转移脚本与队列处理
监控是持续运行的,迁移则是定期手动触发(比如一个月或半年一次)。转移脚本读取 pending.json,把存档从 AppData 搬走,原地建符号链接。
1. 转移脚本设计要点
- 从
pending.json读取待处理项。 - 对每一项,先确定目标目录名。优先使用手动填写的
remark,否则从解码后的 exe 路径自动提取游戏文件夹名,若都失败则回退到原始目录名。 - 通过
robocopy将源目录完整复制到D:\GameSaves\目标名。 - 复制成功后,删除源目录,并在同一位置创建一个 目录链接 指向新路径。
- 将迁移关系记录到 Markdown 格式的日志文件
存档迁移记录.md中。 - 处理成功的条目从队列移除,失败则保留,等待下次重试。
2. 几个关键设计
安全删除和链接创建,这是最容易翻车的环节,有两个点必须处理好:
- 复制前如果目标目录已存在(比如之前迁移过但记录丢了),直接
robocopy会合并文件,可能造成新旧存档混杂。必须先尝试删除已有目标目录,并检查是否真的被删干净;若因文件占用无法完全删除,则中止本次操作,保留队列项。 - 复制后删除源目录时,同样可能因文件占用导致部分删除失败。必须确认源目录已完全消失后,才能创建链接。否则残留目录加上失败的链接创建,会让游戏存档状态混乱。若删除失败,整个迁移视为未完成,保留在队列中,下次重试。
这些检查在脚本中都是以条件判断 + 日志记录的方式实现的,确保一定成功。
迁移记录以 Markdown 表格形式写入存档迁移记录.md,例如:
praygame
D:\GameSaves\祈愿游戏
praygame 游戏存档
rmmz-game
D:\GameSaves\莉可的不可思议差事
莉可的不可思议差事
这样无论后续手动浏览还是用其他工具解析,都非常直观。
队列自动清理:每处理完一批,脚本生成一个新的 JSON 数组,只包含失败的项,覆盖写回
pending.json。成功的自动消失,不需要手动编辑。
设置开机自启
使用 Windows 任务计划程序保证脚本在每次登录时自动运行。
操作步骤
- 打开“任务计划程序”(可以
Win+R输入taskschd.msc)。 - 右侧点击 “创建任务”(不是“创建基本任务”)。
- 名称:
GameSavesMonitor - 配置:
Windows 10,勾选 “使用最高权限运行”。
- 名称:
- 触发器 → 新建:
- 开始任务:
登录时 - 特定用户:选择你的账户(如
DESKTOP-XXX\admin) - 高级设置:延迟任务时间 30 秒(给网络驱动器映射留出时间)
- 确保“已启用”被勾选。
- 开始任务:
- 操作 → 新建:
- 程序或脚本:
powershell.exe - 添加参数:
-WindowStyle Hidden -ExecutionPolicy Bypass -File "D:\Scripts\Watch-GameSaves.ps1" - 起始于(可选):
D:\Scripts
- 程序或脚本:
- 条件 :建议取消“只有在计算机使用交流电源时才启动此任务”(笔记本)。
- 设置 :勾选“如果任务失败,按以下频率重新启动”(间隔 1 分钟,最多 3 次)。
- 确定保存。
验证自启是否生效
- 重启电脑后登录,
Win+R输入taskschd.msc查看显示所有正在运行的任务。 - 检查日志文件
D:\GameSaves\监控调试日志.txt,应包含最新的启动时间戳。
总结
通过这套方案,无论游戏安装在本地还是 NAS,只要启动游戏产生配置文件夹,脚本就会自动记录存档路径和对应的游戏 exe 位置(Base64 编码),并利用任务计划程序实现开机自启,再配合手动或自动迁移脚本,基本可以保证AppData较为干净。
由于所有操作都在 AppData 内进行(删除、创建链接),直接贴出完整脚本容易导致佬们在不理解的情况下误操作,造成数据丢失。因此本文只讲逻辑和关键点,佬们可以根据以上思路自行编写,或让 AI 辅助生成。真有需要的佬可以私信我,如果对某一块的实现细节感兴趣,也欢迎留言交流。
2 个帖子 - 2 位参与者