Files
BakNRet/SoftwareCatalog.psd1
T
Shuery 2d26f78d15 fix: 源文件改存 UTF-8 with BOM,让 Windows PowerShell 5.1 真正可用
改造前:全仓 6/6 个源文件在 5.1 上解析失败(README 却承诺支持 5.1)。原因是文件是无 BOM 的
UTF-8,而 5.1 没有 BOM 就按 ANSI 代码页解码源码,中文变乱码、全角问号吃掉引号,整块语法塌掉。
现在 28/28 个文件在 5.1 与 7 上都解析零错误,E2E 36 项在 5.1 上全绿。

顺带修掉一个被 5.1 掩盖的缺陷:带 [CmdletBinding()] 的脚本在 5.1 上,param() 默认值里
拿不到 $PSScriptRoot(实测为空串,7 上正常)。于是 Backup.ps1 / Restore.ps1 在 5.1 上不传
路径参数就报错退出 —— 而计划任务恰恰不传。E2E 之所以看不见,是因为它总是显式传路径。
8 处默认值全部移到 param() 之后的解析段,沿用本仓库对 -BackupDir 一直在用的写法。

新增三条可重放的约定,让编码不再是一次性动作:
  .gitattributes 接管行尾(本机 core.autocrlf=true,会把工作区改成 CRLF 制造伪 diff)
  .editorconfig 用 charset = utf-8-bom 锁住 BOM
  tools\Set-SourceEncoding.ps1 是规范化脚本,tools\Invoke-* 之外的任何改动之后都能重放
  test.ps1 是唯一验收入口:Encode + Parse + Unit + Smoke + E2E,在 7 与 5.1 上各跑一遍

test.ps1 的 Encode 层直接检查"必须有 BOM"这条规则。加它的原因很实际:实测本仓库用的
编辑工具在保存时会悄悄去掉 BOM,而丢了 BOM 的文件只在 5.1 上出错、在 7 上完全正常,
没有这条检查就会一直漏过去。

已知未修(下一步处理):5.1 上 Unit 有 6 项、Smoke 有 1 项失败,全部源于测试夹具写
临时文件时没指定编码(5.1 的 Set-Content 默认 ANSI),与产品代码无关。
2026-09-26 22:05:42 +08:00

232 lines
8.0 KiB
PowerShell
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<#
.SYNOPSIS
软件目录清单(SoftwareCatalog)。
.DESCRIPTION
定义每个软件在归档内的槽位(Slot)结构,供备份与恢复共用。
一个软件 = 一个归档(归档名就是软件名),包内的顶层目录就是这里定义的 Slot。
结构:
SoftWareName = @{
Slot = @{
Path = 'Absolute\Path'
Exclude = 'Relative\Path'
Include = 'Relative\Path:Absolute\Path'
Encrypt = $false
Description = 'Some information about this slot.'
}
}
.NOTES
字段说明:
SoftWareName 软件名称。不含空格,遵循驼峰大小写。
Slot 插槽。归档内的一层目录:内容进 `<Slot>\`;
Path 是文件时,存成名为 `<Slot>` 的文件本身。
同一软件里不能有两个同名 Slot。规则同 SoftWareName。
Path 路径。需备份或恢复的来源路径,为宿主机上的绝对路径。
Exclude 排除。不需备份的目录,为压缩包内的相对路径。
多个以逗号分隔。相对于本 Slot 的根(即归档内的 `<Slot>\`)。
以“!”打头即“任意层级匹配”(7z 的 -xr!,通配符 `*` / `?`);
要按正则排除写成 `!re:<正则>`(脚本自己展开成精确路径)。
Include 包含。需要追加的目录。
语法:<压缩包内相对路径>:<宿主机绝对路径>。
多个以逗号分隔。
Encrypt 是否加密此归档。默认:$false。
同一个条目里各 Slot 不一致时,整个归档按加密处理。
Description 描述。
#>
@{
AutoDarkMode = @{
DefaultData = @{
Path = '%AppData%\AutoDarkMode'
Encrypt = $true
Description = 'AutoDarkMode 数据。'
}
}
DeepSeekHarness = @{
DefaultData = @{
Path = '%UserProfile%\.dsh'
Encrypt = $true
Description = 'DSH(深度求索)数据。'
}
}
DSHDesktop = @{
DefaultData = @{
Path = '%AppData%\dsh-desktop'
Encrypt = $true
Description = 'DSH 桌面版数据。'
}
}
MicrosoftEdge = @{
DefaultData = @{
Path = '%LocalAppData%\Microsoft\Edge\User Data'
Exclude = '!*Cache,!BrowserMetrics,!component_crx_cache,' +
'!Crashpad,!optimization_guide,!ProvenanceData,' +
'Default\ExtensionActivityEdge,Default\Extensions,Default\Service Worker,' +
'Snapshots,Edge Sidebar,Edge Shopping'
Encrypt = $true
Description = '微软 Edge 浏览器用户数据。
保留:书签/密码/偏好/历史,以及站点数据(IndexedDB / Local Storage)。
排除:缓存、组件缓存、Service Worker、扩展本体(可从商店重装)、遥测与优化数据。
可选排除:Default\IndexedDB、Default\Local Storage、Default\Session Storage、Default\blob_storage、Default\WebStorage。
注意:Edge 常驻时打包会有上百个文件读不到(含 Login Data / Cookies),脚本检测到警告后不会用这份不完整的归档覆盖已有的完整归档。备份前建议先退出 Edge。'
}
}
FastNodeManager = @{
DefaultData = @{
Path = '%UserProfile%\fnm'
Encrypt = $true
Description = 'FNM(Node 版本管理器)数据。'
}
}
INZONEHub = @{
DefaultData = @{
Path = '%AppData%\Sony\INZONE Hub'
Description = '索尼英纵数据。'
}
}
Kazumi = @{
DefaultData = @{
Path = '%AppData%\com.example\Kazumi'
Encrypt = $true
Description = 'Kazumi 数据。'
}
}
Legendary = @{
DefaultConfig = @{
Path = '%UserProfile%\.config\legendary'
Encrypt = $true
Description = 'Legendary(Epic 的开源客户端)的配置。'
}
}
Mnemon = @{
DefaultData = @{
Path = '%UserProfile%\.mnemon'
Encrypt = $true
Description = 'Mnemon(LLM 智能体的持久记忆系统)数据。'
}
}
Obsidian = @{
DefaultData = @{
Path = '%AppData%\obsidian'
Encrypt = $true
Description = 'Obsidian 数据。'
}
}
OpenCode = @{
DefaultConfig = @{
Path = '%UserProfile%\.config\opencode'
Encrypt = $true
Description = 'OpenCode 的配置。'
}
}
OpenSSH = @{
DefaultData = @{
Path = '%UserProfile%\.ssh'
Encrypt = $true
Description = 'SSH 私钥 / 公钥 / known_hosts 等文件。'
}
}
PiliPlus = @{
DefaultData = @{
Path = '%AppData%\com.example\piliplus'
Encrypt = $true
Description = 'PiliPlus 数据。'
}
}
PowerShell = @{
DefaultData = @{
Path = '%UserProfile%\Documents\PowerShell'
Encrypt = $true
Description = 'PowerShell 7 的用户配置与模块。'
}
}
PowerToys = @{
DefaultBackup = @{
Path = '%UserProfile%\Documents\PowerToys\Backup'
Encrypt = $true
Description = 'PowerToys 备份。'
}
}
Scoop = @{
DefaultConfig = @{
Path = '%UserProfile%\.config\scoop'
Encrypt = $true
Description = 'Scoop 配置。'
}
GlobalPersist = @{
Path = '$(if ($env:SCOOP_GLOBAL) { $env:SCOOP_GLOBAL } else { Join-Path $env:ProgramData "scoop" })\persist'
Encrypt = $true
Description = 'Scoop 里各全局应用的持久化数据。'
}
UserPersist = @{
Path = '$(if ($env:SCOOP) { $env:SCOOP } else { Join-Path $env:USERPROFILE "scoop" })\persist'
Encrypt = $true
Description = 'Scoop 里各用户应用的持久化数据。'
}
}
Startup = @{
GlobalLink = @{
Path = '%ProgramData%\Microsoft\Windows\Start Menu\Programs\Startup'
Description = '全局开机启动项(快捷方式)。'
}
UserLink = @{
Path = '%AppData%\Microsoft\Windows\Start Menu\Programs\Startup'
Description = '用户开机启动项(快捷方式)。'
}
}
SteamRomManager = @{
DefaultData = @{
Path = '%AppData%\steam-rom-manager'
Description = 'Steam Rom Manager 数据。'
}
}
TranslucentTB = @{
ScoopData = @{
Path = '$(scoop prefix translucenttb)\settings.json'
Description = 'TranslucentTB 的设置文件(Scoop 安装)。'
}
}
TwinkleTray = @{
DefaultData = @{
Path = '%AppData%\twinkle-tray'
Description = 'Twinkle Tray 数据。'
}
}
WindowsPowerShell = @{
DefaultData = @{
Path = '%UserProfile%\Documents\WindowsPowerShell'
Encrypt = $true
Description = 'Windows PowerShell 5.1 的用户配置与模块。'
}
}
WindowsTerminal = @{
DefaultData = @{
Path = '%LocalAppData%\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json'
Encrypt = $true
Description = 'Windows Terminal 的设置文件。'
}
}
}