Server 2012 离线装 .NET 3.5:0x800F0906 排查
简介面向 Windows Server 2012 系统管理员与运维人员这份 SxS 镜像资源包用于在无完整安装介质或网络受限的环境下补齐 .NET Framework 3.5 所需组件缓解通过 Windows Update 安装时常见的下载失败、速度缓慢与服务启用受阻等问题也可作为旧版应用兼容性部署的本地组件来源。压缩包共 1569 个文件、约 101.69MB以 dll、resx、exe、aspx、config、sql、browser、ini、tlb 等为主覆盖框架运行库、资源文件、配置与安装支撑内容并附随包使用说明便于按目录结构定位所需 SxS 组件。已有 10501 人学习下载。资源提供离线安装所需的本地源适合理解 NetFx3 功能启用与组件依赖关系也可用于排查安装失败时对照文件完整性和路径设置提升在受限网络与断网服务器上的部署效率。1. 那行报错不是系统坏了0x800F0906 卡住的到底是什么一台跑着老业务系统的 Windows Server 2012双击安装包弹出「需要安装 .NET Framework 3.5」点「安装此功能」等一会儿跳出 0x800F0906。换成服务器管理器手动勾选 .NET Framework 3.5 功能还是同一句话无法安装以下功能。这不是系统坏了。从这一代 Windows 开始.NET 3.5 的安装文件不再随系统盘一起落地系统里只剩一个「功能名」真正装的时候才去找源文件。联网机器还能从更新里拉内网离线机器就只能靠一份和系统版本对齐的 sxs 目录把 .net 3.5 安装这件事手动补完。下面按我实际踩过的顺序讲三个错误码各自指向哪里--sxs准确写法是/Source:...\sources\sxs那行命令怎么拼装完怎么验以及装上了却还是起不来的时候该往哪看。2. 三个错误码不是一回事0x800F0906、0x800F081F、0x800F0907 的根因拆解2.1 报错现场长什么样触发条件各不相同同样是「无法完成更改」三条路径完全不同。0x800F0906 的完整提示里通常带一句「Windows 无法从 Windows 更新下载所需文件」这句话已经把根因写在脸上了系统试图联网取载荷但取不到。可能是机器根本不通外网可能是 DNS 解析不了更新地址也可能是上游更新服务被内网策略接管之后那台服务器上压根没有 .NET 3.5 的包。这条错误跟你的命令写法无关跟你有没有指定源有关。0x800F081F 的提示是「找不到源文件」意思是你确实指定了源但系统在那个位置没找到它能用的东西。这一条最容易误判成「路径写错了」实际上路径写对却依然报 081F 的情况非常常见原因集中在三处指向的目录不对指到了 ISO 根目录或sources而不是sources\sxs、目录里的载荷文件和当前系统版本或语言对不上、文件在拷贝过程中被截断。0x800F0907 最少见也最容易查错方向。它一般出现在被域策略管着的服务器上提示大意是「组策略不允许从 Windows 更新下载」或者干脆没有下载动作就直接失败。根因不在系统本身而在「指定 Windows 功能安装和修复的设置」这条策略被指向了内部更新服务器并且勾了「从不安装来自 Windows 更新的功能」。这种情况下你把镜像挂得再对DISM 也不会去读它因为它压根没打算找源。2.2 错误码对照先对号再动手错误码提示关键词根因落点第一动作0x800F0906无法从 Windows 更新下载没有可用源联网路径不通挂载同版本 ISO走/Source0x800F081F找不到源文件源路径不对、版本/语言不匹配、载荷缺失先确认sources\sxs下的 cab 存在0x800F0907组策略阻止修复源被策略指向内部服务器临时还原策略再配合/LimitAccess0x800F0954无法联系更新服务客户端侧更新源不可达同上改走本地源0x80073712组件存储损坏系统组件仓库本身有问题先/Cleanup-Image /RestoreHealth这张表我一般贴在运维记录第一页。因为绝大多数人第一次遇到时只会看到一行「安装失败」然后开始搜「.net3.5安装失败」搜到的方案五花八门有让改注册表的有让重装系统的实际上只要先分清错误码属于哪一类后面能省掉一大半时间。2.3 先判断一件事是没源还是有源被拦在敲安装命令之前花三十秒确认策略状态比装到一半失败再回滚划算得多。组策略相关的注册表位置固定用 reg query 看一眼就行:: 看更新源是否被策略接管返回 0x1 说明走了内部更新服务器 reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU /v UseWUServer :: 看功能修复源是否被强制指定存在这个键就说明策略在起作用 reg query HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Servicing /v RepairContentServerSource :: 顺带确认系统版本和内部版本号后面选镜像要用 systeminfo | findstr /B /C:OS Name /C:OS Version第一条返回0x1说明这台机器的更新行为已经被内部服务器接管此时系统的默认逻辑是「去内部服务器找」而内部服务器大概率没同步 .NET 3.5 的可选组件。第二条如果查到了值说明功能修复源被策略钉死DISM 会优先按那个地址找本地镜像反而被忽略。处理办法是临时把策略还原成「未配置」在本地策略编辑器里进「计算机配置 - 管理模板 - 系统」找到「指定 Windows 功能安装和修复的设置」设为未配置然后执行gpupdate /force让策略立刻生效。装完再改回去。这一步在域环境里要跟管策略的人打个招呼别自己改完就跑否则下一次策略刷新又会被覆盖回去然后你会以为是「装好了又掉了」白折腾一轮。顺带说一句/LimitAccess这个参数的作用就是让 DISM 不要去联系更新服务。很多人以为加上它就万事大吉实际上它只挡住了「联网下载」这个动作挡不住「策略强制指定了另一个源」。所以正确的顺序是先看策略再用/LimitAccess把联网这条路彻底堵死让系统老老实实读你给的目录。3. 挂载镜像补源/Source:...\sources\sxs那行命令的完整写法3.1 挂镜像、认盘符、确认载荷真的在网上把这一步叫--sxs其实 DISM 没有这个参数真实写法是/Source:路径\sources\sxs--sxs只是大家口头的简称。既然是简称就有人真的照着敲--sxs然后得到一句「无效的参数」这也是这类问题里最常见的乌龙之一。挂载镜像我习惯用 PowerShell因为盘符能自动取出来不用盯着「我的电脑」数# 只读挂载 ISO-PassThru 返回对象后面才能取盘符 $iso Mount-DiskImage -ImagePath E:\iso\SERVER2012_R2_X64.iso -PassThru # 从挂载结果里取盘符避免手写盘符写错 $dl ($iso | Get-Volume).DriveLetter Write-Host 源目录: $dl:\sources\sxs # 关键一步确认载荷文件真的在这个目录里 Get-ChildItem $dl:\sources\sxs -Filter microsoft-windows-netfx3-ondemand-package* | Select-Object Name, Length-PassThru不加的话Mount-DiskImage什么都不返回$iso是空的后面取盘符直接报错。Get-Volume拿到的DriveLetter是个字符拼路径时要补冒号。最后那句过滤是关键正常情况下你应该看到一个microsoft-windows-netfx3-ondemand-package.cab大小在两百多兆这个量级。看不到它就别往下走了先解决源的问题——目录里没这个文件DISM 一定会给你 0x800F081F换什么参数都没用。如果Get-ChildItem输出为空而目录本身存在常见原因是这份 ISO 是精简过的安装介质或者你挂的是某个第三方打包的「合辑镜像」。这类镜像的sources\sxs经常被裁掉。判断方法是看sources目录下有没有install.wim或者install.esd有安装映像但没有 sxs 载荷就是被裁过。这种情况只能换回官方原版同版本镜像。3.2 正式安装一行命令四个部分:: 以管理员身份运行 cmd :: /Online 表示对当前运行的系统操作不是离线映像 :: /FeatureName:NetFx3 是 .NET 3.5 的功能名写错会报「功能名称未知」 :: /All 连同父级功能一起启用 :: /Source 指向 sxs 目录注意是目录不是 cab 文件 :: /LimitAccess 阻止 DISM 回连更新服务 dism /Online /Enable-Feature /FeatureName:NetFx3 /All /Source:D:\sources\sxs /LimitAccess :: 立刻看返回码0 才是成功3010 表示需要重启 echo %errorlevel%命令执行过程中会显示进度条走到 100% 之后才是判定时刻。很多人看到进度条满格就以为成了实际上后面的「操作成功完成」才是结论。返回码 0 表示装好了3010 表示装好了但要重启才生效其他任何数字都是失败此时往上翻两屏DISM 会把具体原因打出来那行才是你要拿去搜的东西而不是笼统的「安装失败」。/FeatureName的写法必须精确NetFx3。写成NetFramework3、NetFx35、NETFX3都会失败DISM 的功能名是大小写不敏感但拼写敏感。查当前系统里到底叫什么名字用dism /Online /Get-Features | findstr /I netfx会列出所有带 netfx 的功能名一眼就能对上。3.3/All、/LimitAccess、/Source三个参数各自管什么/Source管「从哪读」可以给多个路径用分号隔开DISM 会依次尝试。实际用的时候给一个就够了给多了反而容易因为某个路径不可访问而拖慢速度。路径里带空格必须加引号这在「D 盘新建文件夹」这种随手起的名字上翻车率极高。/All管「父功能要不要一起开」。.NET 3.5 在功能树里不是叶子节点它下面挂着 WCF 激活、HTTP 激活这些子项。不加/All主功能能装上但依赖它的子功能仍然是关的表现出来就是「装是装上了程序还是起不来」。这一条在后面第 5 章还会再提一次因为它是「安装成功但无效」的头号原因。/LimitAccess管「要不要联网」。不加它DISM 在本地源里找不到东西时会自己转头去问更新服务于是你在内网环境里会看到命令卡住几十秒然后报 0x800F0906——明明给了源却报了个「下载失败」非常迷惑。加上它DISM 就只认你给的路径找不到立刻失败错误信息也更干净。离线环境我建议无脑加。3.4 装完立刻验证三条命令缺一不可:: 1) 看功能状态State 应该是 Enabled dism /Online /Get-FeatureInfo /FeatureName:NetFx3 :: 2) 看注册表标记Install 应该是 0x1 reg query HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.5 /v Install :: 3) 看运行库目录是否落地正常会有 v3.5.30729 这个版本目录 dir C:\Windows\Microsoft.NET\Framework\v3.5.30729第一条看功能状态State : Enabled是终点。如果显示Enable Pending说明还在等重启重启后再查。第二条看注册表Install的值是0x1才算真正注册进系统有些情况下功能状态是 Enabled 但注册表没写程序照样找不到运行库。第三条看物理目录v3.5.30729是 .NET 3.5 的版本号目录存在说明文件确实落地了。这三条我一般连着跑因为它们的失败方式不一样功能状态对但目录不存在多半是安装过程中断目录存在但注册表没写多半是被某些「优化工具」清过三条全对但程序还报错那就是程序侧的问题不是运行库的问题——这时候要去查 IIS 或者应用配置而不是继续折腾安装。4. 换一种写法PowerShell 路径与免挂载的落地做法4.1 ServerManager 模块Install-WindowsFeature的等价写法命令行不止 DISM 一种。Server 2012 上装了 ServerManager 模块可以直接用 PowerShell 写好处是能拿到结构化返回值方便塞进脚本里做批量。# 引入服务器管理模块没有这步会提示命令不存在 Import-Module ServerManager # Net-Framework-Core 就是 .NET 3.5 在功能树里的名字和 DISM 的 NetFx3 是同一个东西 Install-WindowsFeature -Name Net-Framework-Core -Source D:\sources\sxs -IncludeAllSubFeature -Restart:$false-Source的值和 DISM 一样指向 sxs 目录不是 cab 文件。-IncludeAllSubFeature等价于 DISM 的/All把子功能一起带上。-Restart:$false表示先不自动重启方便你先把其他步骤跑完再统一重启不然脚本跑到一半机器重启了后面全断。这条命令返回一个对象Success为True才算成功RestartNeeded告诉你是否需要重启。批量场景下我一般这么写$r Install-WindowsFeature -Name Net-Framework-Core -Source D:\sources\sxs -IncludeAllSubFeature if (-not $r.Success) { Write-Host 失败退出码: $($r.ExitCode) -ForegroundColor Red } elseif ($r.RestartNeeded -eq Yes) { Write-Host 安装完成需要重启 -ForegroundColor Yellow } else { Write-Host 安装完成无需重启 -ForegroundColor Green }ExitCode的取值和 DISM 返回码是同一套语义0成功、3010需重启。有这个东西几十台机器跑一遍就能筛出哪几台失败不用一台台点。如果系统是 2012 R2 并且 PowerShell 版本在 4.0 以上还可以用 DISM 模块的Enable-WindowsOptionalFeature写法更接近客户端系统Enable-WindowsOptionalFeature -Online -FeatureName NetFx3 -Source D:\sources\sxs -All -LimitAccess -NoRestart参数含义和 DISM 一一对应-All对应/All-LimitAccess对应/LimitAccess-NoRestart对应不自动重启。区别在于这条命令在老一些的 2012 上可能提示模块不可用遇到就直接退回 DISM别在这上面耗时间。4.2 没有图形界面把 sxs 目录先拷到本地盘远程到一台机器、又没有挂载 ISO 的权限时我一般把整个 sxs 目录先复制到系统盘再指向本地路径。这样做的好处是断开远程会话之后安装不会中断坏处是占两百多兆空间装完记得清。# /E 含子目录/NFL /NDL 不打印文件列表避免刷屏 robocopy D:\sources\sxs C:\sxs /E /NFL /NDL # 复制完核对文件数和源目录对比一下 (Get-ChildItem C:\sxs -Recurse -File).Count (Get-ChildItem D:\sources\sxs -Recurse -File).Count两个数字必须一致。不一致就是复制过程被中断了最常见的原因是目标盘空间不够robocopy 会在日志末尾提示。这种半截的目录拿去当源DISM 报的就是 0x800F081F然后你会以为是镜像的问题重新下载一遍镜像浪费一晚上。复制完之后把/Source:D:\sources\sxs换成/Source:C:\sxs就行其余参数一律不动。装完用Remove-Item C:\sxs -Recurse -Force清掉。4.3 装完之后的「服务开启」IIS 与 ASP.NET 2.0 注册.net 3.5服务开启这个说法在实际场景里通常指两件事一是运行库本身装上了二是依赖它的服务能起来。前者靠上面几节解决后者经常被漏掉。如果这台机器跑 IIS装完 .NET 3.5 之后还要把 ASP.NET 3.5 的处理程序注册进去否则站点会给你 500.19 或者「无法识别的配置节」。老教程会让你跑aspnet_regiis -i这个做法在 2012 上已经不是推荐路径了正确的方式是启用对应功能# Web-Asp-Net 对应 IIS 里的 ASP.NET 3.5 支持 Install-WindowsFeature -Name Web-Asp-Net # 如果应用用了 WCF还需要 HTTP 激活 Install-WindowsFeature -Name WCF-HTTP-ActivationWeb-Asp-Net装完IIS 管理器里的处理程序映射才会出现v2.0.50727那一组。装之前站点报 500.19装之后正常这个因果关系我在好几台机器上验证过。WCF-HTTP-Activation则是给走 HTTP 协议的服务用的缺了它服务起来但调用方一直超时日志里只有一句含糊的「没有终结点在侦听」排查起来非常费劲。装完这些重启一次 IISiisreset再用浏览器访问站点确认。别只看「功能已启用」就收工服务能不能起来是另一回事。5. 避坑记录五条踩过的坑每条都能多耗两小时5.1 路径指向了 ISO 根目录而不是sources\sxs现象命令里写着/Source:D:\或/Source:D:\sources回车之后十几秒报 0x800F081F提示找不到源文件。你去看路径目录明明存在。原因DISM 不会递归去猜载荷放在哪一层它只认你给的那个目录且要求目录里直接躺着microsoft-windows-netfx3-ondemand-package.cab。指到上一层它翻不到就报错。解决把路径精确到sources\sxs。不确定的时候先dir D:\sources\sxs能看到 cab 文件再执行安装。这一步花五秒能省掉一轮无意义的排查。5.2 镜像版本或语言和系统对不上现象路径完全正确cab 文件也在仍然 0x800F081F或者装到一半回滚。原因拿 2012 R2 的 sxs 去喂 2012或者拿中文版镜像给英文版系统补都会失败。载荷文件是按版本和语言签名的系统在安装时会校验对不上就拒绝。这个错误提示极其含糊只说「找不到源文件」完全不提版本不符。解决用systeminfo里的OS Version和系统语言去挑镜像版本号、语言、架构三项全对上。宁可多下一个镜像也别指望跨版本凑合。5.3 组件存储本身坏了装什么都失败现象换了三个镜像、试了两种命令全部失败错误码有时是 0x800F081F有时是 0x80073712。原因系统的组件仓库WinSxS有损坏DISM 在写入新组件时校验不过。这种情况下源再完美也没用因为问题不在源这一侧。解决先修仓库再装组件。:: 先扫描看有没有可修复的损坏 dism /Online /Cleanup-Image /ScanHealth :: 有损坏就修这一步需要源同样指向 sxs dism /Online /Cleanup-Image /RestoreHealth /Source:D:\sources\sxs /LimitAccess :: 仓库修完再装 .NET 3.5 dism /Online /Enable-Feature /FeatureName:NetFx3 /All /Source:D:\sources\sxs /LimitAccess顺序不能反。先装组件再修仓库等于在坏地基上盖房子修完仓库组件还是缺的。/RestoreHealth跑完会给出修复结果成功之后再执行安装成功率明显不一样。5.4 远程会话里挂载之后盘符不见了现象Mount-DiskImage提示成功但资源管理器里没有新盘符命令里写的D:指向的是本来的数据盘。原因盘符冲突。服务器上本来就有 D 盘ISO 挂载时系统会自动分配下一个可用字母往往不是你以为的那个。远程桌面会话里有时盘符重定向也会干扰导致你看到的和执行时用的不是同一个。解决别猜盘符用Get-Volume取。挂载后立刻执行($iso | Get-Volume).DriveLetter拿到真实字母再拼进命令。或者用-DriveLetter参数在挂载时直接指定一个确定没被占用的字母比如Z。5.5 装上了但老程序还是说缺 .NET 3.5现象三条验证命令全过功能是 Enabled注册表是0x1目录也在但程序启动还是弹「需要 .NET Framework 3.5」。原因八成是漏了子功能或者漏了应用侧依赖。/All没加的情况最常见——主功能装上了WCF 那一层没装程序调用 WCF 的接口就报错而错误文案恰好和「缺 .NET 3.5」长得很像。另一种是 IIS 站点没注册 ASP.NET 3.5表现出来也是类似的错。解决补装子功能再查注册。:: 查看当前 .NET 3.5 下所有子功能状态 dism /Online /Get-Features | findstr /I netfx输出里凡是NetFx3相关的项状态都应该是 Enabled。有 Disabled 的用/All重新跑一遍安装命令补上。IIS 场景再补Web-Asp-Net然后iisreset。这三步做完还有问题就该去查应用程序自己的配置文件了别继续在运行库上绕。6. 快速定位三分钟分清是源、策略还是系统本身我现在接到「.NET 3.5 装不上」这类活不急着敲安装命令先花三分钟做判断。顺序固定先看错误码再看策略最后验源。这个顺序是有讲究的——错误码决定方向策略决定路径通不通源决定最后能不能成。反过来做会在「换个镜像再试试」这种动作上反复循环。判断表如下照着对号就行你看到的大概率是下一步提示里带「从 Windows 更新下载」根本没给源挂同版本 ISO加/Source和/LimitAccess提示「找不到源文件」路径肉眼可见存在路径层级或版本语言不对dir到 sxs 层核对 OS 版本与语言提示被组策略阻止或无下载动作直接失败修复源被策略接管还原策略 gpupdate /force报 0x80073712或换源多次仍失败组件存储损坏先/RestoreHealth再装安装成功但程序仍报错子功能缺失或 IIS 未注册补/All、补Web-Asp-Net具体到操作我一般按这五步走每步都有明确的判定点不做没有输出的动作systeminfo确认版本号、语言、架构据此选镜像。判定点三项和手上的 ISO 完全一致。reg query查两条策略有值就先还原。判定点两条都返回「找不到指定的注册表项」。挂载 ISOGet-ChildItem确认 cab 存在且大小正常。判定点文件名和体积都对。执行 DISM 安装看返回码。判定点0或3010。三条验证命令连跑。判定点状态、注册表、目录三样全对。这五步里任何一步判定不过就停在那一步解决不要往下走。因为后面的步骤依赖前面的结果源不对的时候硬装只会得到一个错误码然后你再拿这个错误码去搜搜到的方案又是从第一步开始的绕一圈回到原点。还有一个细节值得说失败之后别急着重启。很多人一看失败就重启觉得「重启能解决百分之九十的问题」。在 DISM 这个场景里重启会让挂载的 ISO 掉盘/Source路径失效下一次执行直接报路径不存在于是错误码变了你以为遇到了新问题其实是自己制造的。先把错误码和命令行完整记下来再决定要不要重启。从那以后我每次碰这类离线组件安装都强制走一遍「版本—策略—源—装—验」这五步哪怕只有一台机器。血泪经验是省下来的那两分钟最后都变成了两小时。这份资源里放的就是和系统版本对齐的 sxs 源目录以及上面这几组我实际跑通的命令遇到装不上的时候先按第 6 章的顺序对一遍多数情况不用重装系统就能过去。希望帮到你。本文还有配套的精品资源点击获取