拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Windows Server 2012 R2 SxS 并行配置错误修复与补丁安装指南

简介这份资源面向在 Windows Server 2012 R2 Standard 上部署 .NET Framework 3.5 时反复安装失败的系统管理员与运维人员提供官方 SXS 组件源文件用于在离线或受限网络环境中通过指定备用路径完成功能安装。压缩包共 1568 个文件约 85.45MB以 720 个 dll 动态库、180 个 resx 资源文件、84 个 exe 可执行程序为主并包含 aspx、config、sql、browser、tlb、targets、manifest 等类型覆盖 .NET 3.5 运行库、ASP.NET 组件、配置模板与注册表相关文件目录结构基本还原系统组件源形态便于直接挂载为安装源。已有 1799 人学习下载适合需要修复 .NET 3.5 安装报错、搭建离线部署环境或研究 SXS 组件依赖关系的读者参考可省去从系统镜像中手动提取文件的繁琐过程。1. Windows Server 2012 R2 Standard 的 SxS 文件为什么老服务器一打补丁就报“并行配置不正确”一台还在跑业务的老机器Windows Server 2012 R2 Standard某天装个运行库或者打个月度补丁事件日志里蹦出“应用程序无法启动因为应用程序的并行配置不正确”或者弹窗直接点名sxs目录下的某个 manifest。很多人第一反应是重装系统其实问题往往就锁在 WinSxS 这个组件存储里。SxS 是 Side-by-Side 的缩写Windows 用它来并存同一 DLL 的多个版本避免“DLL 地狱”。2012 R2 Standard 作为长期服役的版本WinSxS 目录动辄十几 GB里面塞满了 manifest、策略文件和硬链接。这篇不聊虚的就讲清楚 SxS 文件到底是什么、坏了怎么修、补丁装不上怎么绕、以及哪些操作会把系统搞到无法回滚。适合还在维护 2012 R2 的运维、桌面支持和被“并行配置”折磨过的工程师。2. 先搞懂 WinSxS 里到底存了什么manifest、策略与硬链接2.1 SxS 不是普通文件夹是组件版本数据库WinSxS 位于C:\Windows\WinSxS但它不是让你手动整理的文件仓库。里面每个子目录名都长这样amd64_microsoft-windows-servicingstack_31bf3856ad364e35_6.3.9600.17415_none_xxxx。拆开看amd64是架构microsoft-windows-servicingstack是组件名31bf3856ad364e35是公钥标记6.3.9600.17415是版本none是语言最后是哈希。系统加载 DLL 时不是去System32直接找而是先读 manifest再按这个命名规则定位到 WinSxS 里的真实文件。System32里看到的很多 DLL 其实是硬链接指向 WinSxS。所以删 WinSxS 里的“重复文件”等于自毁。SxS 的核心是 manifest 文件扩展名.manifest里面用 XML 描述组件的依赖、版本和绑定策略。当应用程序请求某个版本的运行库比如 VC 2008 的Microsoft.VC90.CRT系统会去 WinSxS 找对应的 manifest再加载匹配的 DLL。如果 manifest 损坏、版本对不上或者策略文件被改就会报“并行配置不正确”。2012 R2 Standard 默认带 .NET 4.5但很多老工业软件还依赖 .NET 2.0/3.5这些组件的 SxS 文件一旦缺失补丁就会卡住。2.2 用 dism 看清 SxS 的真实状态别靠肉眼数文件很多人喜欢在资源管理器里看 WinSxS 大小那个数字是虚的因为硬链接被重复计算。正确做法是用 DISM 分析组件存储。在 2012 R2 上DISM 版本是 6.3.9600命令和后来 Win10 略有不同。:: 以管理员身份运行 CMD :: 分析组件存储输出到日志耗时较长 dism /online /cleanup-image /analyzecomponentstore :: 查看具体包状态列出所有包 dism /online /get-packages /format:table :: 检查映像健康扫描损坏 dism /online /cleanup-image /scanhealth :: 如果 scanhealth 报错再跑 restorehealth dism /online /cleanup-image /restorehealth/analyzecomponentstore会告诉你“组件存储清理建议”比如“建议清理”或“不建议清理”。/get-packages列出所有已安装的更新包状态列会显示“已安装”“暂存”“安装挂起”。如果某个包卡在“安装挂起”SxS 里对应的 manifest 可能处于半写入状态这就是补丁反复失败的根因之一。/scanhealth扫描损坏但不修复/restorehealth会尝试从 Windows Update 或本地源修复。注意 2012 R2 的/restorehealth默认走 Windows Update如果机器不能出外网需要挂载 ISO 指定/source:wim:D:\sources\install.wim:1 /limitaccess。参数说明/online指当前运行系统/cleanup-image是清理操作/analyzecomponentstore只分析不删除。/format:table让输出可读。/limitaccess阻止 DISM 访问 Windows Update只用本地源。这些命令不会直接删 SxS 文件但会触发组件存储的重新计算。2.3 硬链接与“看起来很大”的 WinSxSWinSxS 里一个文件可能被硬链接到System32、SysWOW64或WinSxS\Manifests。硬链接是 NTFS 特性多个路径指向同一份数据删一个路径不影响其他。所以用dir /s统计 WinSxS 会得到虚高数字。真正占空间的是那些没有硬链接的“备份”组件比如被取代的旧版本。2012 R2 的组件存储清理任务会自动删除超过 30 天的旧组件但前提是系统正常运行了维护任务。如果服务器长期不重启或者维护任务被禁用SxS 会膨胀到 20GB 以上。判断真实占用可以用dism /online /cleanup-image /analyzecomponentstore它会给出“实际大小”和“共享大小”。共享大小就是硬链接贡献的。如果“可回收的包”数量很大说明有旧组件可以清理。但清理前务必确认没有回滚需求因为清理后旧版本 manifest 会被删除补丁卸载可能失败。3. 补丁装不上、报 SxS 错误时的排查与修复路径3.1 先读 CBS 日志别急着删文件Windows 更新和组件安装的详细记录在C:\Windows\Logs\CBS\CBS.log。当补丁报错比如 0x80073712组件存储损坏或 0x800f081f源文件缺失CBS.log 里会有具体是哪个 manifest 或哪个包出错。用findstr过滤错误行:: 查找 CBS.log 中的错误和失败行 findstr /c:Error /c:Failed /c:Cannot C:\Windows\Logs\CBS\CBS.log C:\cbs_errors.txt :: 如果日志太大只看最后 500 行 powershell -Command Get-Content C:\Windows\Logs\CBS\CBS.log -Tail 500 | Select-String -Pattern Error|Failed|Cannotfindstr是原生命令不依赖 PowerShell 版本。/c:指定多个搜索字符串。输出到文件方便用记事本搜。重点看Exec: Failed to pre-commit或Failed to load manifest这类行后面会跟组件名。比如Microsoft-Windows-Foundation-Package~31bf3856ad364e35~amd64~~6.3.9600.16384出错说明基础包有问题。如果 CBS.log 里出现Repair failed或corrupt再跑sfc /scannow。但注意在 2012 R2 上sfc /scannow会调用 DISM 修复如果 SxS 损坏严重SFC 可能卡在 20% 或报“无法修复”。这时不要强制重启先看 CBS.log 里 SFC 的具体错误。3.2 用 DISM 挂载 install.wim 做离线修复当在线修复失败最可靠的是用同版本 ISO 里的install.wim做源。2012 R2 Standard 的 ISO 里sources\install.wim通常包含多个索引Standard 一般是索引 1 或 2。先查索引:: 查看 install.wim 中的版本信息 dism /get-wiminfo /wimfile:D:\sources\install.wim :: 挂载 Standard 索引到 C:\mount mkdir C:\mount dism /mount-wim /wimfile:D:\sources\install.wim /index:1 /mountdir:C:\mount /readonly :: 用挂载的源修复在线系统 dism /online /cleanup-image /restorehealth /source:C:\mount\Windows\WinSxS /limitaccess :: 修复完成后卸载 dism /unmount-wim /mountdir:C:\mount /discard/get-wiminfo列出索引和版本名确认是“Windows Server 2012 R2 Standard”。/mount-wim的/readonly表示只读挂载避免误改。/source指向挂载后的WinSxS目录而不是install.wim本身。/limitaccess防止 DISM 偷偷去连 Windows Update。修复完成后/discard丢弃挂载改动因为只读挂载本来也没改。如果/restorehealth仍然报错看它具体说哪个包找不到。有时需要把C:\mount\Windows\WinSxS\Manifests也加入源路径但 DISM 的/source只接受一个目录。常见做法是先把install.wim里的WinSxS复制到本地硬盘再指向复制后的目录。复制时用robocopy保留硬链接robocopy C:\mount\Windows\WinSxS C:\sxs_source /E /COPYALL /DCOPY:T /R:1 /W:1/E复制子目录包括空目录/COPYALL复制所有属性包括审核信息/DCOPY:T保留目录时间戳/R:1失败只重试一次/W:1等待一秒。复制后把C:\sxs_source作为/source。3.3 手动注册缺失的 manifest 与策略文件有些老软件安装时会往WinSxS\Manifests写自己的 manifest但写一半失败留下损坏文件。系统加载时找不到对应策略就报并行配置错误。这时可以用sxstrace跟踪具体是哪个组件。:: 开始跟踪输出到 trace.etl sxstrace trace -logfile:C:\trace.etl :: 运行报错的程序然后回车结束跟踪 :: 解析跟踪结果 sxstrace parse -logfile:C:\trace.etl -outfile:C:\trace.txttrace开始记录parse把二进制 etl 转成文本。打开trace.txt搜ERROR或Cannot会看到类似Cannot resolve manifest for assembly Microsoft.VC90.CRT。拿到组件名后去正常同版本机器上复制对应的Manifests下的.manifest文件和Policy下的.policy文件。注意策略文件在C:\Windows\WinSxS\Policies下文件名类似x86_policy.9.0.microsoft.vc90.crt_...。复制后不需要注册系统按文件名自动识别。但复制前先备份原文件因为策略文件版本不匹配会导致更严重的加载失败。提示手动复制 SxS 文件只适用于明确知道缺失哪个组件的场景。盲目从其他机器拷贝整个 WinSxS 会导致版本混乱甚至系统无法启动。4. 清理 SxS 的边界哪些能删、哪些一删就翻车4.1 用 DISM 启动组件清理别用第三方工具2012 R2 自带组件清理命令是dism /online /cleanup-image /startcomponentcleanup。它会删除被取代的旧组件版本但保留最近 30 天内的以便回滚。如果加/resetbase会删除所有被取代的版本之后无法卸载已安装的更新。对于长期稳定的服务器/resetbase可以释放大量空间但代价是失去补丁回滚能力。:: 标准清理保留 30 天回滚 dism /online /cleanup-image /startcomponentcleanup :: 激进清理删除所有旧版本不可逆 dism /online /cleanup-image /startcomponentcleanup /resetbase/startcomponentcleanup会先检查组件存储是否健康如果之前有损坏可能直接失败。失败时看 CBS.log通常需要先/restorehealth。/resetbase执行后dism /online /get-packages里很多包会变成“已安装”且无法卸载。如果之后某个补丁导致蓝屏就没法回滚了。所以生产环境慎用/resetbase除非你确定这台机器不再需要卸载任何更新。4.2 这些目录和文件千万别手动删WinSxS 里有些目录看起来像垃圾实际是系统启动和恢复必需的。比如WinSxS\Backup存放组件安装时的备份文件删了可能导致修复失败。WinSxS\Manifests下的.manifest文件是加载入口删任何一个都可能导致对应组件无法加载。WinSxS\Temp是安装过程中的临时目录正常情况下系统会自己清手动删可能中断正在进行的安装。还有WinSxS\FileMaps和WinSxS\Catalogs前者记录文件映射后者存放安全目录签名。删了会导致 SFC 和 DISM 校验失败。网上有些“WinSxS 瘦身脚本”直接删Backup和Temp短期看不出问题但下次打补丁时就会报 0x80073712。血泪经验清理 SxS 只用 DISM不用任何第三方清理器。4.3 清理后补丁回滚失败的补救如果已经跑了/resetbase又需要卸载某个补丁常规的wusa /uninstall会失败因为旧组件被删了。这时只能从备份或同版本机器上恢复。如果机器有系统状态备份可以挂载 VHD 提取WinSxS里的旧版本。如果没有备份最后的后悔药是进入 WinRE用dism /image:C:\ /cleanup-image /revertpendingactions撤销挂起的操作但这只对“安装挂起”有效对已完成的更新无效。更实际的做法是在跑/resetbase之前用dism /online /cleanup-image /analyzecomponentstore确认“可回收的包”数量并导出一份当前包列表dism /online /get-packages packages_before.txt。万一出问题至少知道原来装了哪些包可以手动从 Windows Update 目录重新下载安装。5. 避坑与常见问题SxS 报错排查的 5 条实战记录5.1 现象补丁安装到 99% 回滚报 0x800f081f原因/restorehealth默认从 Windows Update 拉源但服务器不能出外网或者 WSUS 没有同步对应语言包。解决挂载同版本 ISO用/source指定install.wim挂载后的WinSxS并加/limitaccess。如果仍失败检查 ISO 版本是否与系统完全一致Standard 和 Datacenter 的组件不能混用。5.2 现象运行老软件报“并行配置不正确”但 SxS 目录看起来完整原因软件依赖的 VC 运行库 manifest 被某个补丁更新覆盖版本号变了但策略文件没同步。解决用sxstrace抓具体组件名然后从同版本正常机器复制对应的.manifest和.policy文件。复制前备份原文件复制后重启。不要直接重装 VC 运行库因为可能装不上反而留下更多损坏。5.3 现象dism /online /cleanup-image /startcomponentcleanup卡在 20% 不动原因组件存储里有损坏的包清理操作在尝试读取时卡住。解决先跑dism /online /cleanup-image /scanhealth如果报损坏再跑/restorehealth。如果/restorehealth也卡进 WinRE 用离线 DISM 修复。离线命令是dism /image:C:\ /cleanup-image /restorehealth /source:D:\sources\install.wim:1 /limitaccess注意/image指向离线系统盘符。5.4 现象手动删了WinSxS\Backup后SFC 报“无法修复”原因Backup里存放的是组件安装时的原始文件SFC 修复时需要从这里取。解决从同版本机器的WinSxS\Backup复制对应文件或者用install.wim里的WinSxS做源跑/restorehealth。如果损坏严重只能就地升级安装保留数据和程序。5.5 现象/resetbase后想卸载某个更新报“更新未安装”原因/resetbase删除了旧版本组件更新卸载需要旧版本 manifest系统找不到就认为更新不存在。解决没有直接补救只能从备份恢复或重装更新。预防措施生产环境先跑/analyzecomponentstore确认没有回滚需求再执行/resetbase。6. 用 PowerShell 批量校验 SxS manifest 完整性最后一章给一个我常用的校验脚本。2012 R2 自带 PowerShell 4.0不支持Get-FileHash的某些参数但基础功能够用。思路是遍历WinSxS\Manifests下的.manifest文件用[xml]尝试解析解析失败的说明文件损坏。同时对比WinSxS\Policies下的策略文件检查是否有 manifest 没有对应策略。# 校验 SxS manifest 完整性 $manifestPath C:\Windows\WinSxS\Manifests $policyPath C:\Windows\WinSxS\Policies $badManifests () $missingPolicies () # 解析所有 manifest Get-ChildItem $manifestPath -Filter *.manifest | ForEach-Object { try { [xml]$xml Get-Content $_.FullName -ErrorAction Stop } catch { $badManifests $_.FullName } } # 检查策略文件对应关系简化版按名称匹配 $manifestNames Get-ChildItem $manifestPath -Filter *.manifest | Select-Object -ExpandProperty Name $policyNames Get-ChildItem $policyPath -Filter *.policy | Select-Object -ExpandProperty Name foreach ($m in $manifestNames) { $base $m -replace \.manifest$, $found $policyNames | Where-Object { $_ -like *$base* } if (-not $found) { $missingPolicies $m } } # 输出结果 Write-Host 损坏的 manifest 数量: $($badManifests.Count) $badManifests | Out-File C:\bad_manifests.txt Write-Host 缺少策略的 manifest 数量: $($missingPolicies.Count) $missingPolicies | Out-File C:\missing_policies.txt脚本逻辑第一段用[xml]强制解析任何格式错误都会抛异常被 catch 捕获。第二段做名称模糊匹配因为策略文件名和 manifest 文件名不是完全一致但包含相同组件标识。-replace去掉扩展名-like做通配匹配。输出到文本文件方便后续处理。参数说明$manifestPath和$policyPath是固定路径2012 R2 上不变。-ErrorAction Stop让 Get-Content 遇到错误立即抛异常否则会静默继续。Out-File默认 Unicode 编码记事本可读。如果badManifests数量大于 0不要直接删这些文件而是从同版本机器复制替换。如果missingPolicies很多可能是策略目录权限问题先检查Policies目录是否可读。我一般会把这个脚本放在维护脚本库里每次打补丁前跑一次留个基线。如果补丁后badManifests突然增加说明补丁写坏了 manifest可以及时用/restorehealth修复避免问题累积到无法启动。维护 2012 R2 这种老系统靠的就是提前发现和留后路别等蓝屏了才找后悔药。希望帮到你。本文还有配套的精品资源点击获取
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门