专业的 Windows 应用存储重定向工具
将 C 盘应用无损迁移到其他磁盘,释放系统空间,保持应用正常运行
Windows 用户经常面临以下困扰:
- C 盘空间不足 - 大量应用默认安装在 C 盘,导致系统盘空间紧张
- 手动迁移风险高 - 直接移动应用文件夹会导致应用无法运行
- 重装系统数据丢失 - 应用数据存放在 C 盘,重装系统后需要重新配置
Viap 的解决方案:
- 使用 Windows 符号链接(Symbolic Link)技术,将应用无损迁移到其他磁盘
- 迁移后应用正常运行,无需修改任何配置
- 支持一键恢复,随时将应用迁回原位置
┌─────────────────────────────────────────────────────────────┐
│ Viap │
├─────────────────────────────────────────────────────────────┤
│ Frontend (React + TypeScript + Tailwind CSS) │
│ ┌─────────────┬─────────────┬─────────────┐ │
│ │ AppMigration│ MigHistory │ Settings │ ← 页面 │
│ ├─────────────┴─────────────┴─────────────┤ │
│ │ AppList │ DiskUsageBar │ Toast │ Modal │ ← 组件 │
│ ├──────────────────────────────────────────┤ │
│ │ CSS Variables │ Component Styles │ ← 样式系统 │
│ └──────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ Tauri IPC Bridge (@tauri-apps/api) │
├─────────────────────────────────────────────────────────────┤
│ Backend (Rust) │
│ ┌──────────────────────────────────────────┐ │
│ │ lib.rs — 模块枢纽(35 个 Tauri 命令) │ │
│ ├──────────────────────────────────────────┤ │
│ │ system/ │ │
│ │ • disk_usage.rs 磁盘容量扫描 │ │
│ │ • icon.rs EXE/DLL 图标提取 │ │
│ ├──────────────────────────────────────────┤ │
│ │ storage/ │ │
│ │ • data_dir.rs 数据目录配置管理 │ │
│ │ • history.rs 迁移记录持久化 │ │
│ ├──────────────────────────────────────────┤ │
│ │ folder_manager/ │ │
│ │ • mod.rs 大文件夹发现与迁移 │ │
│ ├──────────────────────────────────────────┤ │
│ │ app_manager/ │ │
│ │ • cache.rs 内存级应用缓存 │ │
│ │ • scanner.rs 三级扫描引擎 │ │
│ │ • snapshot.rs 应用快照与图标 URL │ │
│ │ • migration.rs 应用迁移引擎 │ │
│ │ • uninstaller.rs 卸载与残留清理 │ │
│ │ • detector.rs 特殊目录检测 │ │
│ │ • log_macros.rs 统一日志宏 │ │
│ ├──────────────────────────────────────────┤ │
│ │ models.rs 共享数据结构 │ │
│ │ utils.rs 文件系统工具函数 │ │
│ └──────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ Windows OS │
│ • NTFS Symbolic Links (符号链接) │
│ • Registry (注册表) │
│ • File System (文件系统) │
└─────────────────────────────────────────────────────────────┘
viap/
├── src/ # 前端源码
│ ├── components/ # React 组件
│ │ ├── AppList.tsx # 应用列表(含批量选择 + 流式扫描进度提示)
│ │ ├── CleanupModal.tsx # 残留清理弹窗
│ │ ├── DiskUsageBar.tsx # 磁盘使用率
│ │ ├── FilterSelect.tsx # 下拉筛选组件
│ │ ├── MigrationModal.tsx # 迁移进度弹窗
│ │ ├── ProjectPromoModal.tsx # 项目推介弹窗
│ │ ├── TargetPickerDialog.tsx # 迁移目录选择弹窗
│ │ ├── TitleBar.tsx # 标题栏(集成 Tab 导航 + 磁盘状态)
│ │ ├── Toast.tsx # 通知组件
│ │ ├── UpdateNotification.tsx # 自动更新横幅
│ │ └── WarningConfirmDialog.tsx # 高风险路径确认弹窗
│ ├── pages/ # 页面
│ │ ├── AppMigration.tsx # 应用迁移页(还原/卸载/批量)
│ │ ├── LargeFolders.tsx # 数据迁移页
│ │ ├── MigrationHistory.tsx # 迁移历史页(搜索/筛选/分页/详情面板)
│ │ └── Settings.tsx # 设置页(幽灵清理/导入导出)
│ ├── store/ # 全局状态
│ │ └── appStore.ts # 应用列表模块级单例缓存
│ ├── hooks/ # 自定义 Hook
│ │ ├── useDangerousPathCheck.ts # 危险路径检测(迁移前拦截)
│ │ ├── useTheme.ts # 主题切换
│ │ └── useUpdater.ts # 自动更新检测(check/download/进度跟踪)
│ ├── utils/ # 工具函数
│ │ ├── logger.ts # 统一日志工具
│ │ └── migrationMessages.ts # 迁移错误/内部状态码中文化
│ ├── styles/ # 样式系统
│ │ ├── variables.css # CSS 变量定义
│ │ └── components.css # 通用组件样式
│ ├── App.tsx # 主应用
│ ├── index.css # 全局样式
│ └── types.ts # TypeScript 类型定义
├── src-tauri/ # Rust 后端
│ ├── src/
│ │ ├── main.rs # 程序入口
│ │ ├── lib.rs # 模块枢纽(35 个命令注册)
│ │ ├── models.rs # 共享数据结构
│ │ ├── utils.rs # 文件系统工具函数
│ │ ├── system/ # 系统接口层
│ │ │ ├── disk_usage.rs # 磁盘容量/使用率扫描
│ │ │ └── icon.rs # 图标提取(内存缓存 + SHA1 磁盘缓存,跨重启命中)
│ │ ├── storage/ # 存储层
│ │ │ ├── data_dir.rs # 数据目录配置管理
│ │ │ ├── history.rs # 迁移记录持久化(JSON)
│ │ │ └── size_cache.rs # 目录大小 SWR 缓存(启动秒发缓存,后台重算更新)
│ │ ├── folder_manager/ # 文件夹管理层
│ │ │ └── mod.rs # 大文件夹发现、迁移与恢复
│ │ └── app_manager/ # 应用管理层
│ │ ├── mod.rs
│ │ ├── cache.rs # 内存级应用缓存(AppCache 全局单例,含图标复用保护)
│ │ ├── disk_scan_policy.rs # 启动阶段 HDD/SSD 扫描策略
│ │ ├── snapshot.rs # 应用列表持久化快照 + viap-icon 图标 URL
│ │ ├── scanner.rs # 流式扫描引擎(注册表 → LNK → FS 三级,分批推送)
│ │ ├── migration.rs # 迁移引擎(6 步流程:验证 → 占用检测 → 空间检查 → 复制 → 删除源 → Junction)
│ │ ├── uninstaller.rs # 卸载/残留扫描/强制删除
│ │ ├── detector.rs # 特殊目录动态检测
│ │ └── log_macros.rs # 统一日志宏
│ ├── capabilities/
│ │ └── default.json # Tauri 权限配置
│ ├── icons/ # 应用图标
│ ├── Cargo.toml # Rust 依赖
│ └── tauri.conf.json # Tauri 配置
├── scripts/ # 工具脚本
│ ├── generate-icons.js # PNG 图标生成
│ └── generate-ico.js # ICO 文件生成
└── package.json # Node.js 依赖
- Node.js >= 18.0
- Rust >= 1.70
- Windows 10/11 (仅支持 Windows)
# 安装前端依赖
npm install
# Rust 依赖会在构建时自动安装npm run tauri devnpm run tauri build-
管理员权限
- 创建符号链接需要管理员权限
- 请以管理员身份运行应用
-
迁移前检查
- 确保目标磁盘有足够空间
- 关闭正在运行的目标应用
- 建议先备份重要数据
-
不建议迁移的应用
- BLOCKED(绝对拦截):系统核心组件、浏览器安装目录、GPU 驱动 — 迁移必然导致系统级损坏
- WARNING(需确认):开发工具(VS/JetBrains/VSCode)、虚拟化软件(VMware/VirtualBox)、数据库(MySQL/PostgreSQL 等)、安全软件 — 需完全停止相关服务并确认免责声明后方可继续
- 详见用户手册中的完整危险路径分级规则表
-
迁移后注意
- 迁移后的应用通过符号链接访问
- 请勿删除目标位置的文件
- 如需卸载应用,建议先恢复到原位置
- 如果目标位置已存在同名目录,Viap 会弹出中文确认提示;只有用户确认后才会覆盖并重试迁移
- 错误类 Toast 会默认停留更久,鼠标悬停时暂停自动关闭,长错误和路径会自动换行,便于截图反馈问题
- 数据迁移会自动识别常见开发者缓存/包目录,如 Gradle、Maven、npm/Yarn、Cargo/Rustup、pip/uv、NuGet、Claude Code 和 Codex;未检测到的内置目录不会占用列表
- 设置页“关于”区域提供更新日志入口,可直接查看 GitHub 上的 CHANGELOG
- 仅支持 NTFS 文件系统
- 目标磁盘必须是本地磁盘(不支持网络驱动器)
- 部分应用可能因硬编码路径而无法正常工作
项目提供了图标生成脚本:
# 1. 生成各尺寸 PNG 图标
node scripts/generate-icons.js
# 2. 生成 Windows ICO 文件
node scripts/generate-ico.js源 SVG 文件位于 src-tauri/icons/icon.svg
应用启动后自动检查新版本,发现更新后一键下载安装:
- 自动检测:启动 3 秒后静默检查,有新版本时通知栏提示
- 手动检查:设置页点击「检测更新」按钮,结果即时反馈
- 下载进度:横幅实时显示百分比进度条,可随时取消下载
- 安全取消:取消下载后立即中止后台流程,不会意外重启应用
- 自动检查失败不影响正常使用,无弹窗打扰
发行包说明:
- 普通安装版:支持启动后自动检查和安装更新。
- WebView2 离线安装版:安装包内置 WebView2 运行环境,适合系统无法联网安装运行环境的设备。
- 便携版 ZIP:解压后直接运行,配置和默认数据保存在程序目录;便携版不会自动检查更新,请从 GitHub Releases 手动下载新版本。
- 首帧后显示窗口:Tauri 主窗口默认隐藏,前端首帧挂载后再显示,避免 WebView 初始化期间暴露白屏
- 主题启动页:启动时展示约 2.4 秒的主题化动画启动页,使用正式 Logo 并跟随浅色/深色主题;应用快照、磁盘信息和迁移记录在启动页显示期间并行预热
- 页面按需挂载:启动时仅挂载应用管理页,数据迁移、迁移记录和设置页在首次访问时再初始化,降低低配设备首屏压力
- 背景兜底:根节点提前应用主题背景色,减少窗口显示前后的纯白闪烁
- 字体大小:设置页「外观 → 字体大小」支持 12-16px 自定义调整,并提供标准、适中、较大快捷档位
- 全局生效:应用管理、数据迁移、迁移记录和设置页会统一跟随字号设置,列表行高也会随字号轻微调整,避免高分辨率屏幕文字过小
应用列表采用流式加载架构,告别"等待全部扫描完成才能看到结果":
- 三级扫描引擎:Tier 1 注册表(~85% 命中,<200ms)→ Tier 2 LNK 快捷方式(~10%)→ Tier 3 文件系统扫描(~5%)
- 应用快照秒开:扫描完成后写入
{data_dir}/cache/app_snapshot.json,下次进入应用管理页先推送snapshot阶段,立即显示上次列表,再由后台扫描校验刷新 - 流式推送:每个扫描阶段完成后立即通过
scan-progress事件推送到前端,Tier 1 完成即可显示首批应用 - 图标懒加载:应用项只携带
http://viap-icon.localhost/<hex>URL,前端<img>按需请求真实 PNG;后端协议处理器命中图标磁盘缓存或即时提取,避免 Base64 批量 IPC - 大小后台计算 + 持久化缓存:SWR 策略,启动时秒发缓存值,后台异步重算;冷启动/机械硬盘场景大幅提速
appStore模块级单例:应用列表缓存在模块作用域内,Tab 切换零 IPC 恢复,不重新扫描- 搜索/筛选保持:搜索关键词和筛选条件跨 Tab 保持,用户无感知
- 列头排序:点击「名称」或「大小」列头,按拼音/体积升序降序排列,纯本地排序,刷新后重置
- 扫描耗时开关:设置页「其他设置 → 显示扫描耗时」可控制应用管理页左侧定位调试浮层,通过
scan-performance事件展示 snapshot、registry、shortcuts、filesystem、icons 和 sizes 阶段耗时;折叠后仅保留小图标,手动刷新也会重新生成本次耗时,便于用户反馈时截图定位慢阶段 - 快照校验提示:冷启动命中持久化快照时,页面先显示快照列表,再用小提示反馈后台全量校验状态;当扫描结果与快照不一致时会提示列表已更新
- 机械硬盘优化:启动冷阶段识别磁盘介质,仅延后已知机械硬盘的非系统盘深度扫描;SSD 和无法识别类型的磁盘正常扫描。首页会提示被延后的盘符并明确要求点击刷新按钮,手动刷新时仍执行完整文件系统扫描
- AppData 迁移建议:不建议整体迁移 AppData、Local 或 Roaming,应该按软件颗粒度选择数据目录;带许可证校验、系统服务或驱动的软件不适合使用目录链接
- 微信数据目录:兼容新版微信
Documents\xwechat_files,同时保留旧版Documents\WeChat Files回退检测
Viap 使用 Windows Win32 API 提取应用的真实图标:
- ExtractIconExW - 从 EXE/DLL 文件中提取图标
- GetIconInfo / GetDIBits - 将图标转换为位图数据
- 两级缓存 - 内存缓存(进程内命中)+ 磁盘缓存(跨重启命中),自动失效
- 自定义协议 -
viap-icon协议直接返回 PNG 字节,前端优先使用icon_url,仅兼容旧数据时回退icon_base64
微软商店应用(Microsoft Store / UWP / MSIX)通常位于 C:\Program Files\WindowsApps,由 Windows 包部署、权限、签名和更新机制统一管理。Viap 不建议也不作为可迁移应用处理此类目录;部分商店应用会在 Windows 设置中提供「移动」按钮,也可通过存储设置调整新应用默认保存位置,应优先使用 Windows 提供的迁移方式。
首页顶部显示所有本地磁盘的使用情况:
- 支持横向滚动,适配多分区用户
- 系统盘(C:)优先显示并高亮
- 根据使用率显示不同颜色(绿色 < 70% < 黄色 < 90% < 红色)
支持多选应用一键批量迁移:
- 每行 hover 显示复选框,顶部「全选未迁移」快捷操作
- 选中后显示浮动「批量迁移 (N)」按钮
- 选择统一目标目录后按序自动执行,单应用迁移失败不影响后续
- 完成后汇总通知(成功/失败数量)
点击已迁移应用的「还原」按钮时:
- 按钮立即切换为 loading 态(spinner + "还原中")
- 还原完成/失败后自动恢复,配合 Toast 通知结果
支持迁移系统文件夹、应用数据和自定义文件夹:
系统文件夹:
- 桌面 (Desktop)、文档 (Documents)、下载 (Downloads)、图片 (Pictures)、视频 (Videos)
应用数据(动态检测路径,含注册表/配置文件回退):
- 微信 / 企业微信 / QQ / 钉钉 / 飞书(含 6 个候选路径)
- Chrome 缓存 / Edge 缓存 / VS Code 扩展 / npm 全局包
迁移特性(与应用管理页一致):
- 进度弹窗 — 复用
MigrationModal,扫描阶段持续显示已扫描文件数/体积,复制阶段显示已复制体积和百分比 - 扫描计划复用 — 迁移前扫描一次生成复制计划,同时用于空间检查和复制执行,避免空间统计与复制列表各扫一遍磁盘
- 恢复进度可见 — 应用管理、数据迁移、迁移记录的恢复/还原按钮会显示后端推送的百分比
- 安全取消 — 迁移进行中可取消,后端自动回滚已复制文件;关闭弹窗需二次确认
- 批量迁移 — 支持全选/多选文件夹,一键批量迁移到统一目标目录,按序执行,失败不影响后续
- 异步非阻塞 —
migrate_large_folder改为主线程 async + spawn_blocking,返回MigrationResult,行为与migrate_app一致 - 进程占用检查 — 迁移前检测关联进程,非系统文件夹被占用时提示关闭,系统文件夹允许强制继续
- 系统文件夹风险提示 — 风险确认弹窗(
RiskConfirmModal)仅在系统文件夹迁移前显示,非系统文件夹直接启动
安全特性:
- 系统文件夹迁移前显示风险警告
- 自动检测进程占用,提示关闭相关应用
- 支持一键恢复到原位置
- 迁移进度实时可见,可随时安全取消
- 大小始终推送事件(即使为 0),避免前端永久显示 "--"
Viap 的强力卸载对标 Geek Uninstaller 等专业工具,提供完整的卸载 → 残留扫描 → 安全清理链路:
卸载命令执行:
- 预览卸载命令(
preview_uninstall),在确认对话框中展示 - 四层命令解析回退:registry_path → DisplayName 匹配 → InstallLocation 匹配 → 文件系统扫描(含 "unin"/"uninstall"/"卸载")
- 三级回退执行策略:直接 exe → cmd /C → start /wait
- 自动检测权限不足 → PowerShell Start-Process -Verb RunAs 提权重试
- 静默参数追加(/S /silent /verysilent /qn /quiet)
- 轮询注册表 + 文件系统确认卸载完成(含 Inno Setup fork 延迟适配)
强制删除(Force Remove):
- 当应用卸载程序损坏/缺失时,自动提供强制删除选项
- 直接删除安装目录(三级回退:直接删 → 清除只读 → takeown + icacls)
- 清理注册表 Uninstall 键
残留扫描(三路并行):
- 文件系统扫描:AppData / LocalAppData / ProgramData / 安装路径,深度 5
- Uninstall 注册表扫描:HKLM + HKCU × 3 路径
- 发布商路径扫描:Software\ × 4 路径(HKLM/HKCU × 普通/WOW6432Node)
- 文件关联扫描:Software\Classes\Applications\ × 2 路径
- 扫描时机修正:卸载完成后才触发,适配便携/绿色软件的安装检测
残留清理弹窗:
- 紧凑设计(640px 宽),可滚动列表,所有项目默认选中
- 类型标签 + 路径 + 大小在一行内展示
- AlertTriangle 警告图标提示不可恢复
安全清理:
- 系统目录黑名单(Windows、System32 等)
- 注册表安全校验(拒绝 Microsoft/Windows、要求 ≥3 级路径)
- 批量选中 + 一键清理,按体积降序排列
用户设置保存在 localStorage 中:
- 默认应用迁移目录 —
defaultAppTargetPath:应用管理页迁移时优先使用此路径 - 默认数据迁移目录 —
defaultDataTargetPath:数据管理页迁移时优先使用此路径 - 两个默认路径均会校验是否为 C 盘(C 盘路径视为无效,强制引导重新选择)
- 删除文件移入回收站(可关闭,关闭后直接彻底删除)
- 数据存储目录自定义(支持迁移到自定义路径,自动复制历史数据)
- 旧版
defaultTargetPath配置自动升迁为defaultAppTargetPath
迁移操作时统一遵循以下约定,确保用户始终明确目标位置:
- 如已设置非 C 盘默认目标 → 弹出确认框:使用默认位置 或 自定义目录
- 如未设置或为 C 盘路径 → 弹出引导框:前往设置(跳转设置页)或 自定义目录
- 选择「自定义目录」后调用系统文件夹选择器
- 应用管理和数据管理使用独立的默认路径配置
迁移历史记录保存在 %APPDATA%/viap/migration_history.json:
- 原子写入:先写入临时文件 (
.json.tmp),再重命名覆盖目标文件,防止断电/崩溃导致数据损坏 - 自动备份:每次保存前自动备份上一版本到
.json.bak - 搜索/筛选/排序:支持按名称搜索、按类型(应用/文件夹)筛选、按时间/名称/大小排序
- 分页显示:每页 20 条记录,底部页码控件
- 链接健康检查:并发检查(最多 5 路)+ localStorage 缓存(TTL 5 分钟),区分"可修复(数据完整,橙色)"和"严重损坏(数据丢失,红色)"两种异常状态
- 记录详情面板:点击行展开完整路径、精确时间、记录 ID、链接状态等详细信息
- 还原前空间检查:通过 sysinfo 检查目标盘可用空间(需 ≥ 1.1× 文件大小),空间不足时拒绝操作,保证 Junction 不被提前删除
- 恢复前进程占用检测:必须在删除 Junction 前检测进程占用,提前拒绝恢复操作,防止 move_dir 中途失败导致数据分裂
- 迁移/恢复回滚保护:迁移复制阶段遇到遍历、元数据、写入或校验错误会中止并清理目标副本;删除源目录前会先创建临时链接预检,预检失败时源目录保持不动;恢复阶段先复制回原路径并校验,成功后再清理目标副本,失败时保留目标完整数据并尝试恢复目录链接
- 普通目录保护:区分"上次恢复未完成(target 存在,可修复)"和"数据已恢复(target 不存在)"两种场景,给出具体修复步骤
- 恢复并发保护:同时恢复多个项目时自动排队,防止互相干扰
- 大文件夹恢复统一入口:通过
restore_app按 record_type 自动分发,确保 history 记录状态正确更新 - 迁移覆盖保护:目标目录有残留时弹窗确认后自动清理;检测到原路径仍是链接时拒绝覆盖,防止误删数据
- 幽灵链接清理:两步操作 — 先扫描预览(只读)→ 确认后执行清除;可检测三种异常:目标数据丢失、链接断裂、原路径消失
- 历史导出/导入:支持导出到指定目录备份,从备份文件导入合并(按 ID 去重)
- 版本字段:支持未来格式升级的平滑迁移
项目使用模块化 CSS 变量系统,定义在 src/styles/variables.css:
- 颜色变量:
--color-primary,--color-success,--color-warning,--color-danger - 间距变量:
--spacing-1到--spacing-16(基于 4px) - 圆角变量:
--radius-sm,--radius-md,--radius-lg,--radius-xl - 阴影变量:
--shadow-sm,--shadow-md,--shadow-lg
- 在对应功能模块中实现核心逻辑(如
app_manager/、storage/、folder_manager/) - 在
src-tauri/src/lib.rs中注册命令路由(直接引用模块路径或创建委托函数) - 前端通过
invoke('command_name', { args })调用
MIT License
欢迎提交 Issue 和 Pull Request!