简介针对Windows Server 2012 R2及SQL Server部署中频繁出现的.NET Framework 3.5安装失败——提示找不到源文件或需要指定源位置——这套亲测有效的修复资源提供了终极解决思路。包内共1568个文件涵盖720个dll动态库、180个resx资源文件、84个exe可执行程序及56个sql脚本等同时包含config、targets、reg等配置与注册表文件能够满足离线安装、组件修复和系统配置等多种场景。压缩包整体约99.19MB结构完整适合云服务器管理员、运维工程师及数据库部署人员使用。已有10328人学习下载实测可绕过“指定源位置”报错帮助快速完成.NET 3.5功能启用避免在无数无效方案中反复试错。1. 装个 .NET 3.5 卡到怀疑人生Windows Server 2012 的经典翻车现场在一台全新的 Windows Server 2012 上装 SQL Server前置检查第一项就是 .NET Framework 3.5。服务器没有外网双击安装包半天没反应添加角色和功能向导转了一圈然后弹 0x800F0906去网上搜了一堆所谓离线包下一个放进去还是同样的错最后只能对着屏幕发懵。这个场景在 Server 2012 / 2012 R2 上实在太过常见SQL Server 2012、2014 的完整安装向导把 .NET 3.5 当作硬性前置项缺了它整个安装流程都走不下去而系统默认又不会给你直接装上这个老框架。问题的根子在于Windows Server 2012 默认不启用 .NET 3.5在线安装只有一条路就是走 Windows Update而离线安装要求你必须有一个和当前系统版本严格匹配的源文件sxs 目录。不是随便找个 .NET 3.5 安装包就能糊弄过去的版本对不上、源目录权限不对、Windows Update 服务被策略锁住任何一个环节出问题都表现为无法安装 .NET 3.5而且报错还长得完全不一样。这篇笔记就是写给卡在这一步的人从版本识别、离线源准备到三条安装路线和五个常见报错的救法照着跑完SQL Server 前置检查就能稳稳变绿。2. 动手前先分清版本和源Server 2012 与 2012 R2 的坑不一样2.1 先确认系统版本避免拿错离线源很多人栽在第一步根本不清楚自己那台机器到底是不是 2012 R2就随便在网上找了个 sxs 压缩包。Windows Server 2012 的正式版本号是 6.22012 R2 是 6.3两个系统的 .NET 3.5 离线源是不通用的把 2012 的源装到 2012 R2 上报错就是 0x800F081F。先花三十秒把版本确认下来后面能少走两个小时的弯路。# 用 systeminfo 看操作系统版本那一行 systeminfo | findstr /B /C:OS 名称 /C:OS 版本 # 用 PowerShell 直接读系统信息 Get-CimInstance Win32_OperatingSystem | Select-Object Caption, Version, BuildNumbersysteminfo的输出里OS 版本如果是 6.2.9200 就是 Windows Server 20126.3.9600 就是 2012 R2。这个数字直接决定你要找哪个离线 sxs 源。另一个容易忽略的点是系统架构x64 和 x86 的源包也不能混用服务器绝大多数是 x64但个别老机器会有 x86 的情况确认一下没坏处。拿到结论之后我一般会把系统版本号用便签贴在服务器机箱上或者在远程桌面的壁纸上写上版本号。听起来很玄学但在维护几十台服务器的环境里分辨哪台是什么版本靠肉眼根本不行每次下载离线源之前先核对一遍版本这是我后来再没在源文件上翻过车的习惯。2.2 离线源文件sxs 目录该长什么样把这台服务器要用的离线安装资源准备好压缩包解压之后你会看到sources\sxs这个典型的目录结构。很多人不知道 sxs 目录是什么它其实就是 Windows 的按需功能组件存储位置装 .NET 3.5 时系统不是去执行一个 exe 安装包而是从这个目录里的NetFx3.cab提取组件文件。理解这一点很重要因为你在网上找到的大多数所谓 .NET 3.5 安装包实际上是给客户端系统用的运行库放到服务器上用 DISM 装根本不认。正确做法是解压对应的 sxs 目录然后把它放到一个稳定路径下比如C:\sxs不要在服务器上挂载 ISO 直接引用光盘路径。原因有两个一是服务器可能装完系统之后光驱会被占用来做别的或者物理机重启后光盘不见了再运行安装就会出现找不到源的诡异情况二是共享盘或外接存储可能因为驱动问题间歇性掉线。我踩过一次性价比很高的坑明明刚才还看得到光盘里的 sxs装到一半提示找不到源文件一查是光盘休眠了。2.3 系统里的三个前置状态检查打开服务器管理器之前先看三个状态。第一是 Windows Update 服务很多人会用组策略把 Windows Update 停掉这在断网环境很常见但 .NET 3.5 的功能添加核心也会去访问 WU服务停了在线方式必挂。第二是看系统有没有已挂起的重启如果系统在等你重启安装更新任何功能添加操作都可能报 0x800F0922。第三是看 .NET Framework 4.x 是否可写如果 4.x 的某次更新把目录权限改掉了3.5 装的进度也会受影响虽然不太常见但碰到了很头疼。用管理员的 PowerShell 窗口执行下面这个检查一次把三个状态全看掉# 检查 Windows Update 服务状态 Get-Service -Name wuauserv | Select-Object Name, Status # 检查系统是否待重启注册表里 PendingReboot 如果为 1 就先把重启做了 Get-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing -Name PendingReboot -ErrorAction SilentlyContinue # 检查 .NET 4.5 的版本号Server 2012 自带 4.5 Get-ItemProperty HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full | Select-Object Releasewuauserv的 Status 如果不是 Running要么启动服务要么就老老实实走离线安装的 DISM 路线不要白费力气去图形界面点。PendingReboot这个键如果存在而且值是 1先重启服务器再继续装否则后面所有功能添加都可能报系统忙。Release 值只要存在就行它主要告诉你 4.x 框架在不在3.5 的安装过程需要和 4.x 共存不要指望把 4.x 卸了装 3.5这俩不是替代关系。3. 正式安装图形向导、DISM、PowerShell 三条路线怎么选3.1 图形界面路线服务器管理器添加功能如果服务器有图形界面大多数人的第一反应是从服务器管理器里点。操作路径是打开服务器管理器 → 添加角色和功能 → 功能选项卡 → 勾选 .NET Framework 3.5 Features → 指定备用源路径填C:\sxs然后让它跑。这个流程本身不复杂但这里有一个特别折磨人的点在安装过程中向导界面会出现一个指定备用源路径的输入框它默认让你填的是安装介质根目录不是 sxs 目录本身。常见错误是往这个框里填C:\sxs\sources\sxs或者填C:\sxs之后系统仍提示找不到源。正确做法要分清楚如果你指定的是包含sources\sxs的介质根填根路径如果已经把 sxs 单独拷出来了填 sxs 所在的那一层路径也就是包含NetFx3.cab的那一层。我自己习惯直接把 sxs 文件夹里的内容放到C:\sxs下也就是让C:\sxs\NetFx3.cab存在这样填写C:\sxs肯定能识别。# 如果图形界面走不动先用 PowerShell 把功能启用起来 Install-WindowsFeature -Name Net-Framework-Core -Source C:\sxsInstall-WindowsFeature是服务器管理器底层使用的 cmdlet-Name Net-Framework-Core是 .NET 3.5 功能在系统里的完整代号-Source指向刚才准备的 sxs 路径。这个方法的好处是比图形界面更直观成功与否直接反映在命令返回值里不会出现向导界面转了十分钟然后一句话不说消失的情况。3.2 DISM 路线离线源安装最稳的一条如果服务器是 Server Core 环境或者图形界面因为各种原因完全没法用DISM 是唯一的路径也是我个人最推荐的方式。它不像服务器管理器那样依赖 WU 服务只要源路径里文件完整几乎不会出现幺蛾子。dism /online /enable-feature /featurename:NetFx3 /all /source:C:\sxs /limitaccess这个命令的参数值得逐一说清楚。/online表示操作当前运行中的系统不要动离线映像/featurename:NetFx3是目标功能名注意大小写无所谓但这个拼写必须一字不差/all表示启用该功能的所有父功能.NET 3.5 有一堆附属组件这一步必须带/source:C:\sxs指定功能源的搜索路径/limitaccess则是让 DISM 只从指定路径和系统自带 Windows 目录里找源文件不要连 Windows Update。这个参数是断网服务器的救命稻草少了它系统会去尝试 WU 然后等半天超时失败。命令跑完会有进度条走到 100% 之后提示操作成功完成。出现报错也不要关窗口DISM 会把具体的错误码打出来比如Error: 0x800F0906这个错误码在下一章我们逐条拆。一个容易被忽视的点是DISM 命令本身要以管理员权限运行普通管理员组用户的 cmd 窗口如果 UAC 没提权命令会直接拒绝执行。3.3 PowerShell 按需功能方式另一种等价写法除了 DISM还有一条 PowerShell 的原生语法也可以启用 .NET 3.5它调用的底层机制和 DISM 是一致的但更细化的参数直观一些。注意这里和刚才的Install-WindowsFeature是同一类命令不过下面这个写法带-LimitAccess行为更加接近 DISM 的死磕本地源逻辑。# 启用功能并限制只能从本地源获取 Enable-WindowsOptionalFeature -Online -FeatureName NetFx3 -All -Source C:\sxs -LimitAccessEnable-WindowsOptionalFeature是 Windows 8 / Server 2012 时代新增的 cmdlet和 DISM 参数一一对应-Online对应 /online-FeatureName NetFx3对应功能名-Source指定源路径。区别主要在返回形式上PowerShell 会返回一个RestartNeeded字段告诉你是否需要重启。我一般用这个命令来判断装的进度如果看到RestartNeeded : False心里就踏实了。用它还有一个小好处如果你不确定系统当前 .NET 3.5 的启用状态可以先执行Get-WindowsOptionalFeature -Online -FeatureName NetFx3看到State : Disabled再执行启用更规范。DISM 没有这种查询带看的方式要靠另一个命令查看是的这是个小差异。3.4 装完后别急着重启先看状态再动手无论用哪条路线装完之后系统会提示你要不要重启。经验是如果提示 RestartNeeded 是 False就不用重启直接确认结果如果是 True别犹豫重启。但重启之前先做一次确认用下面命令看安装状态Get-WindowsOptionalFeature -Online -FeatureName NetFx3 | Select-Object State Get-WindowsFeature Net-Framework-Core | Select-Object Name, InstallState如果返回State : Enabled或者InstallState : Installed说明核心已就位。这时候再去控制面板启用或关闭 Windows 功能里看.NET Framework 3.5 Features 前面的复选框应该是实心钩状态。这里插一个容易自欺欺人的现象有些人装到一半看到对话框显示成功就直接去跑 SQL Server 安装程序结果前置检查还是红回头再看原来功能启用了但没启用完全。原因后头细说现在只要记住装完组件之后去 IWR 里把所有子项都展开看一眼HTTP Activation 和非 HTTP 激活这些附加项该勾就勾。4. 常见安装失败排查五个我踩过且能救回来的坑4.1 0x800F0906报错千千万这个最常见现象是运行 DISM 或者服务器管理器添加功能后报错Error: 0x800F0906后面往往还跟一句The source files could not be downloaded。这个报错出现在没有外网的服务器上简直是标配它表示系统想要从 Windows Update 拉取源文件失败。原因有两种一是服务器根本连不上更新服务二是本地组策略把 WU 访问给锁了。解决的第一步是给命令加上/limitaccessDISM或者-LimitAccessPowerShell强制系统不要去找 Windows Update。第二步检查本地策略gpedit.msc→ 计算机配置 → 管理模板 → 系统 → 指定 Windows 更新设置如果配置自动更新被禁用连带着按需功能也会受影响。把这个策略改成未配置或者直接从注册表删掉对应项再重新运行安装命令就能过。如果策略确实不能被改动有些生产环境被域策略锁死那就彻底放弃向导用 DISM 加 LimitAccess源路径指对就能绕过 WU 依赖。4.2 0x800F081F源文件存在却找不到十有八九版本对不上现象比较诡异明明指定了C:\sxs里面NetFx3.cab就在那DISM 却报Error: 0x800F081F提示找不到源文件。很多人会陷入死循环反复确认路径甚至把权限改成 Everyone 可读也没用。原因我后来才明白这个报错不只是看路径还要校验源文件的版本与当前系统是否匹配。Windows Server 2012 的 sxs 装到 2012 R2 上就是这样文件看得见系统就是不肯用。解决的办法很笨但有效去拿到和当前系统 BuildNumber 完全一致的安装介质或 sxs 源。怎么看有没有拿对回到第二章的Win32_OperatingSystem查询记住 BuildNumber再去源的sources\sxs里找一个带有版本号的文件和系统版本核对。顺手还要看一个东西如果系统装过某些重要更新比如 2012 R2 打了一些补丁之后旧的 sxs 源可能也会失效需要到补丁对应的更新包里去提源不过这种场景在纯离线环境的比例很小核对 BuildNumber 基本够用。4.3 0x800F0907策略强制从 Windows 更新拉取源现象是 DISM 执行到一半报Error: 0x800F0907提示因为组策略设置无法从 Windows 更新下载源。这个和 0x800F0906 的区别在于后者是系统连不上 WU 而失败前者是系统明明能连 WU但被策略告知不许从 WU 拉取或者反过来策略要求必须从 WU 拉取而本地离线源被忽略。出现这个错说明这台服务器的组策略里面有关于从 Windows 更新下载功能的强制规定。解决办法是查注册表HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate下面如果存在DisableWindowsUpdateAccess或者其他策略残留会影响功能源选择。我一般直接用 DISM 指定源路径的同时加/NoRestart不是这个报错的解药正解是临时删策略键安装完成后再把策略恢复回去。改注册表之前记得先备份键值生产服务器上乱动组策略是有风险的事能不动就不动能动就要留后悔药。4.4 0x800F0922系统重启挂起和镜像占用并发现象是 DISM 报Error: 0x800F0922这个错误码很杂多数和重启状态或系统服务状态有关。有一次我怎么都装不上一直报这个错后来发现是服务器挂载了 DVD 镜像而且光驱正在被占用来做系统备份同时系统里有一个待重启的文件重命名操作卡着系统组件服务。解决思路分两步先重启一次把系统状态清干净再确认光驱或者镜像被释放。如果重启之后还报看 CBS 日志C:\Windows\Logs\CBS\CBS.log里面会打出更细的信息比如某个组件存储的锁被占用。排查锁占用一般我会先停掉 Windows Search 服务和 BITS 服务再重试这两个服务在功能安装期间确实可能干扰组件存储。4.5 安装明明成功SQL Server 前置检查还是红的最让人血压升高的一种情况是这个DISM 显示操作成功PowerShell 里查状态也是 Enabled但打开 SQL Server 安装中心跑到安装规则那一步.NET Framework 3.5 这一项依然是红色的失败。原因是 SQL Server 检测的不仅仅是 .NET 3.5 运行库本体它会看 .NET 3.5 SP1 的具体版本号。Server 2012 的 sxs 源不同批次提供的 .NET 3.5 SP1 版本会有差别如果系统里装载的是某个月度更新后的版本而 SQL Server 要求的是更具体的版本区间就会出现这种功能在满足不了的错位。解决方法是去注册表确认版本HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.5下的Version值正常应该是3.5.30729.xxx如果看到的是停在 3.5.30729.01 没打 SP1 补丁就缺 KB 补丁。Server 2012 上需要确认的是系统有没有装全该装的更新如果服务器完全离网又没法补这个版本那就只能换一个更新版本的 sxs 源重新装没有别的捷径。这个场景里 SQL Server 安装日志也会给出具体提示把sqlservr.err打开看里面会写清楚到底缺什么组件。5. 装完怎么验证跑通别急着开 SQL Server 安装包我吃过一次亏DISM 装完 .NET 3.5看着屏幕上的操作成功完成就以为万事大吉直接去跑 SQL Server 安装程序结果前置检查第四项还是红的整个人当场傻眼。所以从那以后我每次装完都强制自己走一遍完整的验证流程几分钟的事能省掉后面半小时的返工。验证其实就四步按顺序执行。# 第一步确认功能状态 Get-WindowsOptionalFeature -Online -FeatureName NetFx3 | Select-Object State # 第二步确认注册表版本 Get-ItemProperty HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.5 | Select-Object Version, SP # 第三步确认程序集文件真的落盘了 Test-Path C:\Windows\Microsoft.NET\Framework64\v3.5 Test-Path C:\Windows\Microsoft.NET\Framework\v3.5第一步如果State不是Enabled说明刚才的操作根本没生效回头要看 CBS 日志找原因。第二步的Version读到3.5.30729.01且SP为 1说明 .NET 3.5 SP1 就位如果 SP 是 0 或者键不存在SQL Server 那一关还是过不去。第三步是查看两个目录是否存在Framework64那个是 64 位程序在用的Framework是 32 位兼容层两个目录同时存在才算完整。SQL Server 安装向导会同时检查这几个维度。第四步是实际跑一段目标代码验证运行库可用别只看文件在不在文件在不一定能运行起来。写一个三行的小程序用 .NET 3.5 编译并执行一遍能跑就说明运行环境真的通了。# 第四步用 csc 编译一个最简单的控制台程序进行运行时验证 Set-Content -Path C:\test35.cs -Value class T{ static void Main(){ System.Console.WriteLine(ok); } } C:\Windows\Microsoft.NET\Framework\v3.5\csc.exe /nologo /out:C:\test35.exe C:\test35.cs C:\test35.exe这段代码做的事非常朴素用 .NET 3.5 自带的 C# 编译器csc.exe把一个只输出 ok 的程序编译成 exe然后执行它。如果第二行能找到csc.exe说明编译器和工具链都已经装好执行后看到 ok说明运行时也正常。这是一个不管 SQL Server 还是任何依赖 .NET 的地方都能用得上的终极确认手段。四步全绿之后再打开 SQL Server 安装中心前置检查里 .NET 3.5 那一项会直接变成绿色对勾往下走就不会再被卡住了。这套流程看起来很基础但它就是能拦截掉我前面写的四个翻车场景比任何嘴硬都有说服力。从那以后我每装一台新服务器无论部署的是什么应用都会强制走一遍这套验证再继续虽然多花五分钟但换来的是后续装数据库、装中间件时彻底不用在这个老框架上再做第二次功课。希望帮到你。本文还有配套的精品资源点击获取