AppData中游戏配置文件自动监控与迁移实践(NAS + 本地双库)

AppData中游戏配置文件自动监控与迁移实践(NAS + 本地双库)
AppData中游戏配置文件自动监控与迁移实践(NAS + 本地双库)

前言

目前我把游戏分别放在本地D:\game和NAS的G:\game(映射盘符)上运行(主要是gal和一些SLG太占空间了,又不想删)。长时间后,Local,Roaming,LocalLow 里会有各种游戏生成的存档和配置文件目录。删游戏时这些目录并不会自动消失,AppData 越来越臃肿,想手动清理又怕删错,备份更是无从下手
于是我写了一套 PowerShell 脚本:实时监控文件夹创建,自动记录游戏路径和存档位置,并在确认后将存档迁移到统一目录,在原位置留下符号链接。这样既能把存档集中管理,又能让 AppData 保持干净。不过,NAS 映射盘符是整个过程里最大的坑(但大多佬们似乎用不到)。本文将分享我从“映射失败”到“稳定挂载”的全过程,以及脚本在中文转码、路径匹配、去重、队列管理等方面踩过的坑和最终方案。

而且我现在的环境很特殊:NAS 和主机用网线直连,主机通过 ICS 让 NAS 共享校园网。下一篇博客会补充 NAS 实战中的更多内容(为此我花了一周在学习网络通信协议)。

:magnifying_glass_tilted_right:手动查找并迁移已有文件

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

:bow_and_arrow:NAS 盘符映射

1. 在 Windows 中映射 NAS 文件夹

我的 NAS 型号是绿联 Dxp4800plus,通过 ICS 共享网络,设置的私网IP 为 192.168.137.20。我把所有游戏放在 NAS 共享文件夹ACG(原名acg资源,后来改名)下,并映射到主机的 G: 盘。
正确映射方法(一定要勾选“登录时重新连接”)

  1. 右键“此电脑” → “映射网络驱动器”。
  2. 驱动器选择 G:,文件夹选择NAS设备\ACG
  3. 必须勾选"登录时重新连接",不然后面开机自启会出问题。

用校园网连接NAS时,在网络可能会找不到设备,需要先进入WLAN把校园网从专用切换为公用,再在网络里重新转为专用,才能发现 NAS 设备。我现在也没搞清楚根本原因是什么,如果佬们知道正确的修改方法请告诉我。

2. 几个踩坑点

踩坑 1:修改共享名称后映射失效

当我把共享文件夹从acg资源改名为ACG后,就无法进入之前映射好的G:盘了。这是因为映射驱动器指向的远程路径是 \\...\acg资源,而实际共享已不存在。
解决方法

  • 先删除旧映射G盘
  • 按照上述步骤重新映射到新文件夹ACG

一旦修改 NAS 共享名,必须同时更新所有客户端的映射,并更新脚本中的路径

踩坑 2:到底该用盘符(G:)还是 UNC 路径(\IP\share)?

这是困扰我最久的问题(主要是不停打开游戏和脚本测试,还要不断删除对应的文件和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都配置上,让脚本自己去匹配。

不知道为什么,在powershellcd \\192.168.137.20\ACG\game却没有问题

踩坑 3:开机自启时 G 盘还未连上

设置任务计划程序开机启动脚本后,发现脚本虽然运行了,但始终检测不到 NAS 上的游戏。日志显示 [注意] 未检测到游戏进程
原因:用户登录后,系统需要几秒钟来恢复网络驱动器。而脚本在登录瞬间就执行了,此时 G: 盘还不存在。
解决方案:在任务计划程序的触发器设置中,添加 “延迟任务时间 30 秒”(或更长,如 60 秒),这样脚本会等待网络和映射完全准备好再启动。

:eye:实现自动化监控脚本

核心需求:

  • 监控三个存档常用目录:%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 下的文件夹创建事件。
  • 事件触发后:
    1. 跳过已存在的连接点或排除文件夹。
    2. 延迟 3 秒,给游戏时间完成写入。
    3. 获取正在运行的进程,匹配路径是否以 D:\gameG:\game 开头。
    4. 将匹配到的第一个游戏 exe 路径转为 Base64(避免 JSON 中的转义和乱码问题)。
    5. 将存档路径、游戏 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。若有,直接跳过,不重复添加。这样即使链接目录被误触创建事件,也不会污染队列,同时也避免了后续转移脚本重复处理。

:wheel:转移脚本与队列处理

监控是持续运行的,迁移则是定期手动触发(比如一个月或半年一次)。转移脚本读取 pending.json,把存档从 AppData 搬走,原地建符号链接。

1. 转移脚本设计要点

  • pending.json 读取待处理项。
  • 对每一项,先确定目标目录名。优先使用手动填写的 remark,否则从解码后的 exe 路径自动提取游戏文件夹名,若都失败则回退到原始目录名。
  • 通过 robocopy 将源目录完整复制到 D:\GameSaves\目标名
  • 复制成功后,删除源目录,并在同一位置创建一个 目录链接 指向新路径。
  • 将迁移关系记录到 Markdown 格式的日志文件 存档迁移记录.md 中。
  • 处理成功的条目从队列移除,失败则保留,等待下次重试。

2. 几个关键设计

安全删除和链接创建,这是最容易翻车的环节,有两个点必须处理好:

  • 复制前如果目标目录已存在(比如之前迁移过但记录丢了),直接 robocopy 会合并文件,可能造成新旧存档混杂。必须先尝试删除已有目标目录,并检查是否真的被删干净;若因文件占用无法完全删除,则中止本次操作,保留队列项。
  • 复制后删除源目录时,同样可能因文件占用导致部分删除失败。必须确认源目录已完全消失后,才能创建链接。否则残留目录加上失败的链接创建,会让游戏存档状态混乱。若删除失败,整个迁移视为未完成,保留在队列中,下次重试。

这些检查在脚本中都是以条件判断 + 日志记录的方式实现的,确保一定成功。

迁移记录以 Markdown 表格形式写入存档迁移记录.md,例如:

原 C 盘快捷方式名 实际存储位置 游戏/说明 praygame D:\GameSaves\祈愿游戏 praygame 游戏存档 rmmz-game D:\GameSaves\莉可的不可思议差事 莉可的不可思议差事 这样无论后续手动浏览还是用其他工具解析,都非常直观。

队列自动清理:每处理完一批,脚本生成一个新的 JSON 数组,只包含失败的项,覆盖写回 pending.json。成功的自动消失,不需要手动编辑。

:laptop:设置开机自启

使用 Windows 任务计划程序保证脚本在每次登录时自动运行。

操作步骤

  1. 打开“任务计划程序”(可以Win+R输入 taskschd.msc)。
  2. 右侧点击 “创建任务”(不是“创建基本任务”)。
    • 名称:GameSavesMonitor
    • 配置:Windows 10,勾选 “使用最高权限运行”
  3. 触发器 → 新建:
    • 开始任务:登录时
    • 特定用户:选择你的账户(如 DESKTOP-XXX\admin
    • 高级设置:延迟任务时间 30 秒(给网络驱动器映射留出时间)
    • 确保“已启用”被勾选。
  4. 操作 → 新建:
    • 程序或脚本:powershell.exe
    • 添加参数: -WindowStyle Hidden -ExecutionPolicy Bypass -File "D:\Scripts\Watch-GameSaves.ps1"
    • 起始于(可选):D:\Scripts
  5. 条件 :建议取消“只有在计算机使用交流电源时才启动此任务”(笔记本)。
  6. 设置 :勾选“如果任务失败,按以下频率重新启动”(间隔 1 分钟,最多 3 次)。
  7. 确定保存。

验证自启是否生效

  • 重启电脑后登录,Win+R输入taskschd.msc查看显示所有正在运行的任务
  • 检查日志文件 D:\GameSaves\监控调试日志.txt,应包含最新的启动时间戳。

:ledger:总结

通过这套方案,无论游戏安装在本地还是 NAS,只要启动游戏产生配置文件夹,脚本就会自动记录存档路径和对应的游戏 exe 位置(Base64 编码),并利用任务计划程序实现开机自启,再配合手动或自动迁移脚本,基本可以保证AppData较为干净。

:warning: 由于所有操作都在 AppData 内进行(删除、创建链接),直接贴出完整脚本容易导致佬们在不理解的情况下误操作,造成数据丢失。因此本文只讲逻辑和关键点,佬们可以根据以上思路自行编写,或让 AI 辅助生成。真有需要的佬可以私信我,如果对某一块的实现细节感兴趣,也欢迎留言交流。

2 个帖子 - 2 位参与者

阅读完整话题

来源: LinuxDo 最新话题查看原文