封装走到第四步,基本上就是临门一脚了。前面三步我们把一台虚拟机里的 Windows 10 从裸系统一点点养成"我想要的样子":语言时区、驱动、运行库、输入法、任务栏布局、资源管理器视图、常用工具,全都调到位。但这时候的系统本质上还是"一台具体的电脑"——它带着这台虚拟机的身份信息、带着某个用户已经登录过的痕迹、带着 OOBE 已经走完的状态。你要是直接把这个盘整盘拷到另一台机器上,轻则首次开机不弹开箱体验、账户配置乱七八糟,重则驱动栈对不上硬件、系统更新报错。
第四步要干的事就一句话:把"一台装好的电脑"变成"一份谁都能装的母盘"。具体落地就是三个动作——把系统通用化(sysprep /generalize)、准备一份无人值守应答文件、用 DISM 把系统盘捕获成 install.wim。这三件事听起来都不复杂,但每一步都有坑,而且坑的位置往往不在命令本身,而在命令执行之前的环境状态。下面我就按实际操作的顺序,把这一步掰开讲清楚。
1. 第四步在整个封装流程里到底解决什么问题
1.1 一台"装好的电脑"和一份"能装机的映像"差在哪
很多人第一次做封装,卡住的地方是概念没分清。你在虚拟机里装好的那套系统,是实例状态,它绑定在具体硬件和具体用户上;而你要交付的东西是模板状态,它必须能在任意一台 x64 机器上走完首次开机流程。
这两者之间的差距主要体现在四个地方。第一是计算机身份:计算机名、SID、Windows 激活状态里的机器相关信息,都是实例化的。第二是驱动栈:虚拟机用的是虚拟磁盘控制器、虚拟网卡、虚拟显卡,实体机用的是完全不同的硬件,系统必须能在首次开机时重新枚举硬件。第三是用户状态:你调系统的时候一定登录过某个账号,用户配置文件、注册表 HKCU 里的一堆设置都带上了个人痕迹。第四是OOBE 状态:系统已经完成过一次开箱体验,直接拿去装机的话,新机器开机会跳过 OOBE 那一套流程,或者进入一个半吊子状态。
第四步的所有操作,归根到底就是把这四样东西"擦掉并重置",同时保留你辛苦调出来的那些全局设置。
1.2 SID 冲突这件事,别被老帖子带偏
网上关于"封装必须改 SID,不然会冲突"的说法,我建议你用一个更冷静的态度看待。在老版本的 Windows 和特定域场景下,SID 重复确实会造成一些麻烦;但在现代 Windows 10 环境里,绝大多数人会遇到的真实问题并不是 SID,而是计算机名重复、驱动不匹配、OOBE 状态残留这些更直接的东西。
真正要通用化的原因不止一个。sysprep /generalize 除了处理机器标识,还会把驱动库的"已安装"标记重置、把组件的安装状态回滚到可重新枚举的状态、把系统准备阶段的计数推进一格。也就是说,通用化是一个打包动作,不是单一目的。你要理解的是:通用化的核心价值是让系统"重新走一遍硬件检测和首次配置流程",至于 SID,属于顺带处理。
我自己的做法是——不纠结 SID 的传说,把通用化当成标准流程走一遍,该做的做,做完用虚拟机完整验一遍。验证通了,比争论"到底要不要改 SID"有意义得多。
1.3 第四步的交付物清单
为了后面讲得清楚,这里先把第四步结束时你手上应该有的东西列出来。这不是流程建议,只是产物清单:
- 一个已经执行过通用化、自动关机、处于"未配置"状态的系统盘
- 一份 unattend.xml 无人值守应答文件,放在能被自动读取的位置
- 一个 install.wim(或拆分后的 install.swm / 转换后的 install.esd)
- 一个可用于验证的测试虚拟机,以及一份记录部署过程中异常点的笔记
这里面最容易出问题的是第一项。很多人 sysprep 命令敲下去了,看到窗口闪一下就没了,以为成功了,其实日志里已经在报错。所以第四步的验收标准不是"命令跑完了",而是"日志里没有 Error,且后续能完整部署一次"。
2. 跑 sysprep 之前,先把封装环境里的"脏东西"清干净
2.1 应用商店应用:sysprep 翻车的第一大来源
如果你用的是 Windows 10 专业版或家庭版这类带应用商店的版本,那 sysprep 报错的概率会明显上升,而且原因往往非常隐蔽。典型现象是执行 /generalize 后弹出"Sysprep 无法验证你的 Windows 安装"之类的提示,日志里跟着一串 0x80073cf9 或 0x80073d02。
这类报错的根源,是系统里有部分 Appx 包处于"暂存中"或"更新中"的中间状态,sysprep 在做通用化时无法处理这种半完成状态。常见的触发路径有这么几种:你登录了应用商店账号、系统在后台自动更新了内置应用、你手动卸载了某些内置应用的当前用户版本但保留了预置版本、你用了网上那种"一键卸载全部内置应用"的脚本。
这里有一条边界必须讲清楚,也是我踩过坑的地方:不要用Get-AppxPackage -AllUsers | Remove-AppxPackage这类命令一次性剥干净。因为这种做法移除的是"当前已安装的包",而预置包(Provisioned Package)还留在系统里,新用户登录时系统会尝试重新安装这些预置包,结果就是首次登录卡住或者报错。正确的做法分两步走:
# 第一步:查看系统里预置的应用包清单 DISM /Online /Get-ProvisionedAppxPackages | Select-String "PackageName" # 第二步:卸载预置包(这才是真正影响新用户的) DISM /Online /Remove-ProvisionedAppxPackage /PackageName:<完整的包名>如果你铁了心要做精简版,先把预置包清干净,再考虑当前用户的应用。顺序反了,后面很难查。另外还有个稳妥办法:在封装前把网络断开,不要登录任何商店账号,不要手动点开应用商店。这样能躲开绝大部分应用包状态相关的坑。
顺便说一句,如果你选的是 LTSC 2021 这类不带商店的版本,这一整节基本上可以跳过——这也是为什么做企业母盘的人偏爱 LTSC。
2.2 保留存储、休眠文件、还原点:三个体积刺客
清理完应用,接下来处理体积问题。系统盘捕获之后体积多大,直接决定了后续部署速度和 U 盘能不能装得下。有三个东西特别能占地方:
保留存储(Reserved Storage)。Windows 10 1903 之后默认会预留一部分磁盘空间给更新使用,通常几个 GB。封装母盘时没必要留着,命令是:
# 查看当前状态 DISM /Online /Get-ReservedStorageState # 关闭保留存储 DISM /Online /Set-ReservedStorageState /State:Disabled休眠文件。如果你不打算在母盘里保留休眠功能,直接关掉,能省下一块和内存等大的空间:
powercfg /h off系统还原点和卷影副本。调试系统的时候难免创建过还原点,这些点会以卷影副本的形式占空间,而且在捕获时容易被一起打进去。清理命令:
vssadmin delete shadows /all /quiet还有一个容易被忽略的:Windows 更新缓存(C:\Windows\SoftwareDistribution\Download)和C:\Windows\Temp。这两个目录在虚拟机上跑过几轮更新之后,塞个几 GB 很正常。不过要注意,清理更新缓存时别用那种暴力删目录的方式,先把相关服务停掉再删,或者干脆用系统自带的磁盘清理cleanmgr走一遍。
2.3 离线补 .NET 3.5 与依赖运行库的正确时机
有些老业务软件到今天还依赖 .NET Framework 3.5,而 Windows 10 默认只启用 4.x 那一套,3.5 处于"按需启用"状态。如果你封装完再让用户去联网装,那是给自己找麻烦。正确做法是在封装前的系统里就把它启用好,而且用离线源,避免走网络。
具体操作是把安装镜像里sources\sxs这个目录拷到本地,然后执行:
# 离线启用 .NET 3.5,源指向本地 sxs 目录 DISM /Online /Enable-Feature /FeatureName:NetFx3 /All /Source:D:\sources\sxs /LimitAccess/LimitAccess这个参数的意思是禁止系统去联网找源,只用你指定的路径。少了它,在某些内网环境里命令会卡很久然后失败。另外提醒一句,如果你做的是 x86 版本(比如 1909 的 32 位镜像),sxs 源也必须是 x86 的,不能混用 x64 的,这一点在镜像文件命名上有时候不明显,容易拿错。
其他的运行库,比如 VC++ 各个年份的 Redistributable,建议在封装前就用静默参数装好:
# 以 VC++ 2015-2022 x64 为例,/install /quiet /norestart 是通用静默参数 vc_redist.x64.exe /install /quiet /norestart装完之后去"程序和功能"里核对一遍,确认没有被 UAC 或重启提示打断。运行库这种东西,装没装成功只有装机的人知道,用户是不会告诉你"我缺个 MSVCP140.dll"的,他们只会说"软件打不开"。所以母盘里一次装全,是给自己省事。
3. sysprep /generalize 动的是哪些底层状态
3.1 通用化到底改了系统里的什么
sysprep 这个工具老是老,但机制一直没大改。执行/generalize的时候,它主要做四件事,理解这四件事,报错的时候你才知道该往哪看。
第一,移除机器特定的信息。包括事件日志、计算机名相关的部分状态、部分硬件相关的枚举结果。第二,重置驱动安装状态。注意,它不会删除驱动文件,只是把"这个驱动已经针对当前硬件装好了"这个标记清掉,让系统下次开机重新走一遍 PnP 检测。这也是为什么实体机第一次开机会有几分钟的"正在准备设备"。第三,重置安全标识相关数据,也就是大家最关心的 SID 那部分。第四,把系统准备阶段的计数加一,这个计数关系到后面说的次数限制。
还有一个很实用的附带效果:通用化会把当前用户的配置文件标记为待处理,配合应答文件可以做到"新机器首次开机只创建你指定的那个账户"。如果你希望母盘部署后直接进桌面干活,这一条是必须用到的。
有一件事要特别注意:通用化不会清理你留在系统里的用户配置文件。如果你在调试阶段建过三个测试账号,这些文件夹还在C:\Users下。建议在跑 sysprep 前手动把多余的账户删掉,并且用sysprep之前把C:\Users\Default这个默认配置文件保持干净——有些人为了让新用户带上自己的设置,直接把配置复制进 Default,这是可以的,但前提是复制的是"干净"的配置,别把临时文件带进去。
3.2 四个命令行开关的适用场景与组合
sysprep 的命令行参数不多,但组合方式决定了你是"关机等捕获"还是"重启进审核模式"。我把常用组合整理成一张表,方便对着选:
| 参数 | 作用 | 典型场景 |
|---|---|---|
| /generalize | 执行通用化,重置硬件与标识状态 | 所有需要做成母盘的场景 |
| /oobe | 下次开机进入开箱体验流程 | 交付给最终用户的母盘 |
| /audit | 下次开机进入审核模式,以内置管理员身份自动登录 | 还需要在实机上做最后调整 |
| /shutdown | 执行完立即关机,不重启 | 准备进 WinPE 捕获 |
| /reboot | 执行完重启 | 需要立刻验证通用化结果 |
| /unattend:路径 | 指定本次使用的应答文件 | 需要定制首次配置流程 |
| /quiet | 不显示界面 | 批量脚本里使用 |
做母盘最常用的组合是这个:
C:\Windows\System32\Sysprep\sysprep.exe /generalize /oobe /shutdown /unattend:C:\unattend.xml跑完它会自动关机,这时候虚拟机就停在关机状态,你挂载 WinPE 的 ISO 从光驱启动,就能开始捕获了。
还有一个很多人不知道的省事技巧:如果应答文件放在这两个固定位置之一,sysprep 会自动读取,不用加/unattend参数——C:\Windows\System32\Sysprep\Unattend.xml或者C:\Windows\Panther\Unattend.xml。我一般直接把文件放 Panther 目录下,命令能短一截,也少一个路径写错的机会。
3.3 审核模式怎么用,以及"次数限制"的真相
审核模式(Audit Mode)是封装过程中一个被低估的功能。它的进入方式是在 OOBE 界面按 Ctrl+Shift+F3,或者用sysprep /audit /reboot。进入之后系统会以内置管理员身份自动登录,不会走开箱体验那一套,你可以在这台机器上继续装软件、调设置,然后再执行一次 sysprep 把它封起来。
审核模式的实用价值在于:你可以在接近实机的环境里做最后调试,而不是在已经封好的系统上反复折腾。比如某些驱动的安装需要重启才生效,某些软件第一次运行会写入用户级配置,这些在审核模式里处理完,再通用化一次,效果比在普通账户下调试更干净。
关于次数限制,网上流传很多版本。比较可靠的说法是:sysprep 的通用化操作存在次数上限,达到上限后需要重装系统或者重置相关计数才能继续。实际经验是——别把 sysprep 当成可以无限次回调的函数。正确的做法是:在虚拟机上先把所有配置调到满意,快照备份,然后只跑一次通用化。如果中途发现漏了东西,恢复到快照重来,而不是在已经通用化的系统上再跑一遍。这样既躲开次数问题,也避免了状态叠加带来的奇怪故障。
4. 无人值守应答文件:从 Windows SIM 生成到关键字段取舍
4.1 为什么建议用 SIM 生成而不是网上抄一份
unattend.xml 是个 XML 文件,理论上你完全可以用记事本手写。但我不建议,原因有三个:组件名和 pass 名必须完全精确,多一个空格或者大小写错了它就不生效;不同架构(amd64 / x86)的组件名前缀不同,抄来的文件很容易架构不匹配;应答文件出错时的表现是"静默不生效",你根本不知道哪一步被忽略了。
Windows SIM(Windows System Image Manager)是 ADK 里的一个工具,它的价值在于:你把 install.wim 加载进去,它能列出所有可用的组件和设置项,你点选生成,它帮你把 XML 结构写正确。这比抄文件靠谱得多。ADK 安装的时候只勾"部署工具"和"Windows 预安装环境"两项就够用了,不需要全套都装。
用法很简单:打开 SIM,File 菜单里新建应答文件,然后加载映像文件,等它把组件树展开。之后在左侧的组件面板里找到对应 pass,右键添加设置项,在右侧属性面板里填值。填完保存,就是你自己的 unattend.xml。
4.2 oobeSystem 与 specialize 两个 pass 里的必填项
应答文件的 pass(阶段)一共有七个:windowsPE、offlineServicing、generalize、specialize、auditSystem、auditUser、oobeSystem。做母盘封装,重点处理两个就够:specialize和oobeSystem。
specialize阶段发生在系统重新枚举硬件之后、进入 OOBE 之前,适合放计算机名规则、时区、以及需要在这一刻执行的命令。常用的组件是amd64_Microsoft-Windows-Shell-Setup_neutral,里面可以设置TimeZone、ComputerName。计算机名如果留空,系统会随机生成一个,这在批量部署里反而更好——避免所有机器同名。
oobeSystem阶段发生在首次登录界面,这是最关键的 pass。需要配置的典型项包括:
Microsoft-Windows-Shell-Setup下的OOBE节点:HideEULAPage、HideOnlineAccountScreens、HideWirelessSetupInOOBE、NetworkLocation、ProtectYourPCUserAccounts节点:定义本地账户名和密码AutoLogon节点:设置自动登录次数FirstLogonCommands节点:首次登录后自动执行的命令
这里有个经验:NetworkLocation设成Work还是Home,会影响系统首次接入网络时的发现策略。内网批量部署一般设成Work。而ProtectYourPC设成3表示不自动启用推荐的快速设置,这个值决定了使用者首次开机时会不会被一堆隐私选项拦一下。企业环境里通常设3,减少一线部署人员的点击次数。
4.3 自动登录、账户、隐私开关的取舍逻辑
自动登录这块要谨慎。设置AutoLogon的LogonCount为 1,可以让系统首次开机自动以指定账户登录一次,然后再清掉密码相关配置。好处是首次开机不需要人工输密码,适合批量装机。风险是密码会以明文形式写在应答文件里,所以装完之后这个文件要留在系统里、还是清理掉,得提前想好。
我自己的做法是分两套文件:一套给装机人员用(带自动登录和明文密码,装在 U 盘的装机分区里,不进系统盘),一套给最终交付用(不带自动登录)。同一个镜像,用法不同,文件不同,这样既方便又不会把密码留在客户机器上。
FirstLogonCommands是个很实用的口子。你可以用它来执行首次登录时的收尾脚本,比如:
<FirstLogonCommands> <SynchronousCommand wcm:action="add"> <Order>1</Order> <CommandLine>cmd /c "C:\Setup\first-run.cmd"</CommandLine> <Description>首次登录收尾脚本</Description> </SynchronousCommand> </FirstLogonCommands>收尾脚本里可以放:清理临时文件、导入预置的注册表设置、删除桌面上给装机人员看的说明文件、把系统盘剩余空间检测一遍。注意这个脚本是以首次登录用户身份运行的,如果要提权操作,得自己处理 UAC 或者改用RunSynchronous放在 specialize 阶段。
5. WinPE 下用 DISM 把系统盘捕获成 install.wim
5.1 为什么捕获一定要在 WinPE 里做
这是很多人第一次做封装时的疑问:系统都关机了,我在当前系统里能不能捕获?答案是不能,或者说不应该。
原因是 DISM 捕获会读取目标分区的所有文件和各种元数据,包括正在被占用的系统文件。如果你在运行中的系统里捕获当前系统盘,会有大量文件被锁定、读取失败,捕获出来的映像可能看着能装,但装完各种注册表项错乱。而且系统运行时自己会产生新的文件变更,捕获过程中的快照不一致。
所以标准流程是:sysprep 关机 → 挂载 WinPE 启动介质 → 从 WinPE 启动虚拟机 → 在 WinPE 环境里运行 DISM 捕获 C 盘。WinPE 环境下目标系统盘是被完全卸载的,所有文件都能静态读取,捕获结果才干净。
WinPE 介质本身很好做:装完 ADK 之后,用"部署和映像工具环境"里的copype命令生成一个基础结构,再把 boot.wim 塞进 ISO。或者你也可以直接用原版安装镜像 —— 在安装界面按 Shift+F10 调出命令行,同样能跑 DISM。这个办法很实用,因为不用额外做一个 WinPE 启动盘。
5.2 Capture-Image 参数逐项拆解与压缩策略
捕获的基本命令:
dism /Capture-Image /ImageFile:D:\images\install.wim /CaptureDir:C:\ /Name:"Win10-22H2-Base-2025" /Description:"Company base image" /Compress:max /CheckIntegrity /ConfigFile:D:\WIMScript.ini逐个说清楚:
/ImageFile是输出路径,建议输出到另一块虚拟磁盘或者挂载的共享目录,别往要被捕获的分区里写,那是自找麻烦。
/CaptureDir:C:\是要捕获的根目录。注意这里不包括引导分区和恢复分区,这两个分区的内容在部署时由安装程序重新创建,不需要捕获。
/Name和/Description是映像的标识信息。别小看这一项,等你机器上有十几份映像文件的时候,/Get-ImageInfo一查,名字写得清楚的人省半小时。命名建议带上版本、用途和日期。
/Compress:max是压缩级别。可选none、fast、max。max压缩率最高但耗时最长,一份 20 GB 的系统盘压到 8 GB 左右是很正常的,代价是可能在虚拟机上跑四十分钟到一小时。我的建议是:调试阶段用fast快速验证,最终成品再跑max。别为了省十分钟,交付一个臃肿的映像。
/CheckIntegrity会校验文件哈希,捕获过程慢一点,但能确认映像没有损坏。成品必加。
/ConfigFile指向排除列表文件,这个特别值得写。默认情况下 DISM 会排除一部分系统文件,但为了保险,我都自己写一份 WIMScript.ini:
[ExclusionList] \hiberfil.sys \pagefile.sys \swapfile.sys \System Volume Information \$Recycle.Bin \Windows\CSC [CompressionExclusionList] *.mp3 *.zip *.cab第一段是"完全不捕获",第二段是"捕获但不压缩"。页文件和休眠文件这类东西完全没必要进映像,排除掉能省下不少空间。这两个列表按你的实际情况调整,但思路是不会错的——凡是系统会自动重建的东西,都不要打进映像。
5.3 映像超过 4GB:拆包、转 ESD 还是换 NTFS U 盘
捕获出来的 install.wim 超过 4GB 是常事。这时候你会撞上一个很现实的限制:U 盘如果格式化成 FAT32,单个文件最大只能放 4GB 减 1 字节。这就导致镜像拷贝失败,装到一半报错。
三条路可以选:
第一条,拆分映像。用 DISM 把 wim 拆成多个 swm 文件,安装程序能识别:
dism /Split-Image /ImageFile:D:\images\install.wim /SWMFile:D:\images\install.swm /FileSize:3800/FileSize单位是 MB,一般设 3800 到 4000 之间,留一点余量。
第二条,转成 ESD。ESD 是微软自己的压缩格式,压缩率更高,体积通常比 wim 小一截,代价是不能再编辑:
dism /Export-Image /SourceImageFile:D:\install.wim /SourceIndex:1 /DestinationImageFile:D:\install.esd /Compress:recovery /CheckIntegrity第三条,把 U 盘做成 NTFS 或者 exFAT 格式,就不受 4GB 限制了。这条路最近几年越来越常用,因为现在的主板对 NTFS U 盘启动的支持比过去好得多。不过 UEFI 启动对分区格式有要求,如果你走 UEFI 引导,还得考虑 FAT32 的 ESP 分区,实际做法是做一个 FAT32 引导分区加一个 NTFS 数据分区的双分区 U 盘,稍微复杂一点,但一劳永逸。
三条路怎么选?我的经验是:普通 x64 系统盘,拆 swm 最省事;如果你要控制网络传输体积,转 ESD;如果你有自己的装机 U 盘制作流程,直接上双分区 NTFS。
捕获完之后,把 install.wim 替换进原版 ISO 的sources目录,用oscdimg重新打包成可启动 ISO:
oscdimg -m -o -u2 -udfver102 -bootdata:2#p0,e,bD:\ISO\boot\etfsboot.com#pEF,e,bD:\ISO\efi\microsoft\efi\boot\efisys.bin D:\ISO D:\Win10_Custom.iso参数看着吓人,其实就两部分:-bootdata指定 BIOS 引导文件和 UEFI 引导文件,前面那几个是光盘格式相关的通用参数,照抄即可。
6. 部署验证与 sysprep 报错的排查链路
6.1 先看日志:三个目标准确找到
sysprep 出错的时候,报错窗口给的信息通常只有一句话,没什么用。真正有用的信息在日志里。有三个位置必须记住:
| 日志路径 | 内容 |
|---|---|
| C:\Windows\System32\Sysprep\Panther\setuperr.log | sysprep 自身的错误摘要 |
| C:\Windows\System32\Sysprep\Panther\setupact.log | 完整执行过程,体量大 |
| C:\Windows\Panther\setuperr.log | 通用安装阶段错误汇总 |
排查顺序是:先看两个 setuperr.log,找到最后一条 Error,再回到对应的 setupact.log 里搜同样的时间点或者关键词,看上下文。这样比从头读 setupact.log 快得多。另外提醒一句——sysprep 失败后要先把日志拷出来再重试,因为下一次执行会覆盖掉上一次的日志。
6.2 高频报错的定位过程
"Sysprep 无法验证你的 Windows 安装"。这条报错最常见,原因也最多。我碰到过的情况包括:应用包处于暂存状态、系统时间不对导致签名校验失败、某个内置应用被以错误方式卸载。定位方法是在 setuperr.log 里找具体的 HRESULT 码,然后对照应用包清单,把可疑的包用 DISM 移除后重试。
0x80073cf9 或 0x80073d02。这两个码基本都指向应用包状态问题。处理思路是:先把网络断开,用DISM /Online /Get-ProvisionedAppxPackages列出所有预置包,逐个移除可疑项(尤其是有更新记录的),然后重启再跑 sysprep。
通用化过程卡住不动。这种情况我在虚拟机上遇到过几次,原因通常是系统里还有 Windows 更新在后台跑。解决办法是在跑 sysprep 前确认更新服务处于空闲状态,必要时把wuauserv服务停掉。另外虚拟机的内存给太小也会让通用化过程慢得离谱,建议至少 4GB。
通用化成功但部署后首次开卡住。这类问题多半出在应答文件上,比如账户名和密码字段写了系统不接受的字符、AutoLogon次数设置为 0 导致流程卡死在登录界面。排查方法是进 WinPE 后把C:\Windows\Panther\unattendgc\setupact.log拷出来看,这个日志记录了 OOBE 阶段的执行细节。
6.3 虚拟机里跑一遍完整验收清单
母盘做完不做验证,等于没做完。我固定会跑这么一轮:
- 新建一台虚拟机,配置和前面调试用的虚拟机不同(比如换一种磁盘控制器类型、换网卡型号),这样能验证驱动枚举的兼容性
- 用做好的 ISO 启动,走完整安装流程,中途不插任何人工操作
- 首次开机后检查:账户是否正确创建、时区语言是否符合预期、隐藏的 OOBE 页面是否真的没出现
- 打开设备管理器,确认没有大面积的黄色感叹号
- 检查系统盘剩余空间,和预期做对比
- 手动重启两次,确认第二次开机进入正常登录流程而不是又跑一遍 OOBE
这里第 1 条是我特别想强调的——验证用的虚拟机配置一定要和调试用的不一样。你在同一套配置上验证,等于什么都没验证,因为你的母盘本来就是在这套配置上做出来的,兼容性问题根本暴露不出来。换个磁盘控制器类型,就足够筛掉一批驱动没清理干净的母盘。
7. LTSC 2021、22H2 两套底座在封装上的实际差异
7.1 LTSC 2021 为什么是封装圈的省事底座
如果你做的是企业内网、工控机、收银机、教学机房这类不需要应用商店和花哨内置应用的场景,LTSC 2021 是个非常省心的底座。它不带商店、不带大部分 UWP 应用、不带语音助手,这意味着前面 2.1 节讲的整类问题基本不会出现。通用化过程干净利落,报错概率明显低。
它的另一个好处是组件数量少,捕获出来的映像体积天然更小。同样装完驱动和运行库,LTSC 的 wim 通常比同版本专业版小一两个 GB。对于需要网络分发或者 U 盘装机量大的场景,这个差距很实在。
代价也明确:它不带的部分功能你是补不回来的,比如某些依赖商店分发的应用、部分多媒体相关组件。所以选底座之前,先把业务软件的实际依赖摸清楚,别装到一半发现缺东西。
7.2 22H2 与较老版本的注意点
22H2 是 Windows 10 的功能更新终点版本,很多还在维护老系统的企业会以它作为长期底座。做这个版本的母盘有两个地方要注意。
一是更新占用。22H2 后期累积更新体积不小,系统盘在跑过几轮更新之后占用会明显上涨。建议在封装前把更新打到一个稳定点,然后清理更新缓存再捕获,否则映像会虚胖。
二是内置应用的状态更容易变化。22H2 上的商店应用更新比较活跃,调试阶段稍不注意就会把应用更新到暂存状态。我的做法是:调试期间断网操作,需要联网的步骤集中做完,做完立刻断网,最后再跑 sysprep。
如果你手上还有 1909 这类更老版本的镜像要做,基本流程一样,区别在于老版本的驱动库对新硬件支持差一些,捕获前把网卡和存储控制器的通用驱动提前注入会更稳。另外老版本镜像里sources\sxs目录经常被精简掉,如果要离线启用 .NET 3.5,得自己从完整镜像里补回来。
我个人的体会是,封装这件事最花时间的从来不是敲命令,而是清理状态和验证结果。前面三步调系统调得越细,第四步要清理的东西就越多——你装的每一个软件、改的每一项设置、删的每一个应用,都可能在通用化的时候变成一颗雷。所以我现在做封装,习惯是调试阶段就单开一个记录文件,每做一步可能影响封装的操作就记一行,第四步照着清单逐条检查,比事后靠回忆去翻日志高效得多。
还有个小技巧分享给你:母盘的第一个版本永远不要当成最终版发出去。先在虚拟机里完整装三五台,跑一周常规使用,看有没有奇怪的问题冒出来,再定版。那些在部署后第三天才出现的毛病,比如某个计划任务报错、某个服务起不来,靠一次开机测试是发现不了的。