解决SQL Server安装需PowerShell 2.0:检测与修复指南
简介面向需要在Windows更新版本上安装SQL Server 2008 R2的系统管理员与运维人员这份资源用于解决安装过程中因微软移除PowerShell 2.0组件而出现的兼容性报错。压缩包仅6KB共3个文件以HTML说明页为主体并配有一个inscode脚本配置与一个gitignore文件内容精简聚焦于PowerShell 2.0环境修复。已有2375人学习下载说明该问题在旧版SQL部署场景中较为常见。用户通过解压后参照HTML页指引以管理员权限运行PowerShell并调整执行策略为RemoteSigned或Bypass再执行loadGAC.ps1脚本即可将关键组件加载到全局程序集缓存从而满足SQL Server 2008 R2的安装前提。这套方案同样适用于其他依赖PowerShell 2.0的软件能为处理新旧系统兼容性提供直接可用的排错思路。1. 安装SQL卡在需要PowerShell 2.0先定位是引擎缺失还是配置问题安装SQL Server时卡在“需要PowerShell 2.0”通常是给老机器换装SQL Server 2008或2008 R2时撞见的安装界面走到“安装程序支持规则”一项红叉写着未安装PowerShell 2.0“下一步”直接置灰。装系统的同事觉得莫名其妙机器里明明有PowerShell命令行SQL凭什么说不满足懂行的人知道问题不在有没有命令窗口而在引擎版本、注册表键和系统位数这三样东西上。这篇笔记围绕“安装SQL需PowerShell2.0”这个卡点把检测逻辑、补装方法和五个高频翻车现场讲清楚目标是你照着做半小时内从“卡住”走到“通过检查”。适合第一次给旧环境装数据库的运维和DBA也适合排查批量环境时想快速定位短板的工程师。2. SQL安装程序为什么揪着PowerShell 2.0不放检测逻辑与版本真相2.1 安装规则检查SQL在哪一个环节、用什么逻辑判定缺失SQL Server 2008和2008 R2的安装程序不是一上来就拷贝文件而是先跑“安装程序支持规则”这一关。内存、磁盘空间、账户权限、.NET Framework、PowerShell 2.0被逐项判红绿灯其中PowerShell 2.0是“必须为绿色”的硬条件和内存不足属于同一级别不是装完系统后能绕过的软提示。所以你在界面上看到那一行红叉的时候安装流程实际上还没有开始部署任何文件直接点“下一步”是点不动的。为什么偏偏要求2.0而不是1.0SQL 2008时代的安装向导在配置Analysis Services、Reporting Services以及部分数据库引擎功能时需要用PowerShell执行一组ps1配置脚本。这些脚本用到了PS 2.0才引入的模块自动加载机制和部分cmdlet在1.0引擎上根本跑不起来。同时后续管理工具对PS引擎的依赖也在这时候定了型——Management Studio里内嵌的PowerShell窗口、部分维护任务的执行宿主都建立在2.0引擎之上。官方对“建议安装”和“必须安装”分得很清楚PowerShell 2.0属于后者。安装程序的判定逻辑我拆成三步。第一步读注册表HKLM\SOFTWARE\Microsoft\PowerShell\3\PowerShellEngine下的PowerShellVersion要求不低于2.0第二步在系统PATH里解析powershell.exe确认能调起控制台宿主第三步实际尝试调用一个PS 2.0才有的cmdlet比如Get-PSSession看返回是否正常。三步全部通过才显示绿勾。很多人以为注册表里有版本号就算数结果卡在第二步的PATH解析也有人PATH没问题卡在第三步的执行策略上。后面避坑章会把这几类情况逐个展开这里先记住一点SQL检查的是“能不能真正用起来”不是“装没装过”。2.2 各Windows版本的“自带”情况把WMF 2.0和PowerShell 2.0分清楚不同Windows版本对PowerShell的支持差异巨大这是很多误会的来源。我先给一张对照表把常见系统状态列清楚Windows 版本默认 PowerShell 状态是否要单独装 WMF 2.0Windows XP SP3默认没有要装 WindowsXP-KB968930Windows Server 2003 SP2默认没有要装 WindowsServer2003-KB968930Windows Vista SP1/SP2自带 PS 1.0要装 Windows6.0-KB968930需先补 KB961501Windows Server 2008 SP1/SP2自带 PS 1.0要装 Windows6.0-KB968930需先补 KB961501Windows 7 / Server 2008 R2内置 PS 2.0一般不用除非功能被精简或文件损坏Windows 8 / Server 2012 及以上内置 PS 3.0 或更高不用但老版 SQL 检查器可能不认见避坑章这里有一个概念必须先理清PowerShell 2.0 不是单独发布的程序它包含在 WMF 2.0 组件包里。WMF 的全称是 Windows Management Framework除了 PowerShell 2.0 引擎还包括 WinRM 2.0 远程管理组件、对 BITS 后台传输的更新等内容。所以你去下载页面找的时候搜“WMF 2.0”比搜“PowerShell 2.0”更容易找到正确入口文件名通常是 KB968930 对应的补丁包。位数问题也在这时候埋下了伏笔。WMF 2.0 的安装包严格区分 x86 和 x64Windows Server 2008 x64 上如果装了 x86 的包版本信息只会写进 32 位注册表视图SQL的64位安装进程读不到。装完重启再检测依然报红叉。这个场景第五年能遇到多半就是架构选错后面专门写。2.3 用两条命令看清当前PowerShell版本$PSVersionTable与注册表双路检测动手装之前先确认目标机器上现在到底是什么状态。第一步是进入PowerShell控制台直接看版本变量# 检查当前PowerShell版本 if ($PSVersionTable) { # $PSVersionTable 是 PS 2.0 起才有的自动变量 $PSVersionTable | Format-List PSVersion, CLRVersion, PSHome } else { Write-Host 当前没有可用的 PS 2.0 引擎$PSVersionTable 变量不存在 } # 查看执行策略Restricted 会挡住 SQL 安装脚本 Get-ExecutionPolicy逻辑说明$PSVersionTable这个自动变量从PS 2.0才开始存在在PS 1.0控制台里输入它会直接报“找不到变量”。用if判断这个变量是否存在本身就是一种版本探测手段。CLRVersion辅助判断.NET运行时版本SQL安装脚本对CLR版本也有下限要求。Get-ExecutionPolicy这条命令是给后面埋的伏笔如果返回值是Restricted安装时大概率会在中途回滚避坑章4.4会细说。# 注册表方式检测适用于连PowerShell控制台都起不来的机器 $roots ( HKLM:\SOFTWARE\Microsoft\PowerShell\1\PowerShellEngine, HKLM:\SOFTWARE\Microsoft\PowerShell\3\PowerShellEngine ) foreach ($root in $roots) { if (Test-Path $root) { $v (Get-ItemProperty $root -Name PowerShellVersion -ErrorAction SilentlyContinue).PowerShellVersion Write-Host $root - PowerShell $v } else { Write-Host $root - 未找到 } }注意这里为什么要同时查\1\和\3\两个目录PS 1.0引擎的注册表键放在PowerShell\1下而PS 2.0引擎的键被放在了PowerShell\3目录下。这个布局看着像BUG其实是历史包袱——微软为了让老脚本兼容把1.0引擎保留在\1新引擎则沿用了后续版本号的目录习惯。所以你会在注册表里看到版本号写着2.0、路径却带着3的奇怪组合这是正常现象不是装错了。3. 真正把WMF 2.0装上安装包选择、静默参数与自动化脚本3.1 老系统XP/2003/Vista/2008装WMF 2.0前置补丁与静默命令老系统上装WMF 2.0第一步是选对安装包。文件名和系统版本严格对应对照关系如下系统安装包前置条件Windows XP SP3 x86WindowsXP-KB968930-x86-ENU.exe无需额外补丁必须已是SP3Server 2003 SP2 x86/x64WindowsServer2003-KB968930-x86/x64-ENU.exe必须已是SP2Vista SP2 x86/x64Windows6.0-KB968930-x86/x64.msu先装 Windows6.0-KB961501Server 2008 SP2 x86/x64Windows6.0-KB968930-x86/x64.msu先装 Windows6.0-KB961501命令本身很简单但顺序不能错。以Server 2008 SP2 x64为例标准两步是这样rem 在Server 2008 SP2 x64上装WMF 2.0的标准两步走 rem 第一步补KB961501这是WMF 2.0的前提补丁 wusa.exe C:\patch\Windows6.0-KB961501-x64.msu /quiet /norestart rem 第二步装KB968930也就是WMF 2.0本体 wusa.exe C:\patch\Windows6.0-KB968930-x64.msu /quiet /norestart参数说明wusa.exe是Vista和Server 2008专用的更新安装工具/quiet表示静默模式不弹任何交互框/norestart表示装完不自动重启方便你在脚本里安排统一的重启时机。实际部署时建议配合start /wait使用——不加/wait的话命令行窗口不会等安装结束就继续向下执行后面脚本逻辑会乱。装完到%windir%\下找日志文件看末尾有没有明确的成功标识。Server 2003和Windows XP的安装包是EXE格式静默参数略有不同rem Server 2003 SP2 x64 装WMF 2.0 WindowsServer2003-KB968930-x64-ENU.exe /quiet /norestart /log:C:\logs\kb968930.log这里/log参数指定日志输出路径排查失败原因时比默认位置好找。有一点容易被忽略补丁包的语言版本要跟系统语言一致中文系统上强行装ENU包偶尔能装成功但注册表语言键不匹配SQL检查器依然可能不认。遇到“补丁装好了但SQL还是报缺”的情况先把语言因素排掉。3.2 Win7/Server 2008 R2自带PS2.0却被判缺功能修复与位数确认Windows 7和Server 2008 R2是第一个把PowerShell 2.0做成内置组件的系统正常情况下不需要装任何补丁。但“内置”不等于“一定可用”被精简过的系统、中过病毒导致系统文件损坏的系统都可能让SQL检查器找不到PowerShell引擎。第一步先确认系统功能状态用DISM查dism /online /get-featureinfo /featurename:MicrosoftWindowsPowerShell如果返回状态是DisabledWithPayloadRemoved说明功能被整体移除过需要重新启用dism /online /enable-feature /featurename:MicrosoftWindowsPowerShell /all /norestart参数说明/all表示连同父功能一起启用避免只启用一半导致引擎不完整/norestart和前面同理装完由你控制重启时机。dism在Windows 7上支持在线操作不需要进WinPE环境。如果功能状态显示已启用但powershell.exe还是起不来多半是系统文件损坏跑一遍sfc /scannowsfc /scannowsfc会扫描所有受保护的系统文件并用缓存副本修复跑完建议重启再验证。还有一个位数细节值得单独说64位系统里其实有两个powershell.exe一个在System32\WindowsPowerShell\v1.0下64位一个在SysWOW64\WindowsPowerShell\v1.0下32位。SQL安装程序是按自己的架构去System32目录里找的你如果在SysWOW64里看到powershell.exe只能证明32位视图正常证明不了64位视图里有引擎。这类问题自查时很容易看漏。3.3 自动化脚本一个批处理完成版本判断、SP判断与安装分发当机器数量超过3台手工选包就变得不现实。我一般会写一个批处理脚本让它自己判断系统版本、位数和SP级别再去匹配正确的安装包。注意这个脚本不用PowerShell写因为目标机上可能根本没有PowerShell批处理是唯一不会先死掉的兜底方案。echo off setlocal rem 批处理自动判断系统版本/位数/SP匹配WMF 2.0安装包并静默安装 rem 前提把对应的安装包和KB961501放在本脚本同目录 set PKG_DIR%~dp0 rem 第1步判断架构。AMD64是64位其余按32位处理 if %PROCESSOR_ARCHITECTURE%AMD64 ( set ARCHx64 ) else ( set ARCHx86 ) rem 第2步用wmic取系统版本和SP信息老系统都支持wmic for /f skip1 tokens* %%i in (wmic os get caption^,servicepackmajorversion) do ( echo 检测到系统信息: %%i ) rem 第3步按版本号分发安装包 ver | find 6.0 nul if not errorlevel 1 ( echo 当前是Vista/Server 2008先装KB961501再装KB968930 start /wait wusa.exe %PKG_DIR%Windows6.0-KB961501-%ARCH%.msu /quiet /norestart start /wait wusa.exe %PKG_DIR%Windows6.0-KB968930-%ARCH%.msu /quiet /norestart goto :install_done ) ver | find 5.2 nul if not errorlevel 1 ( echo 当前是Server 2003或XP x64用EXE包 start /wait %PKG_DIR%WindowsServer2003-KB968930-%ARCH%-ENU.exe /quiet /norestart goto :install_done ) ver | find 5.1 nul if not errorlevel 1 ( echo 当前是Windows XP x86 start /wait %PKG_DIR%WindowsXP-KB968930-%ARCH%-ENU.exe /quiet /norestart goto :install_done ) :install_done echo 安装命令已执行建议重启后再验证PS版本 endlocal这里有几个边界要解释。PROCESSOR_ARCHITECTURE是cmd内置的环境变量AMD64对应64位系统x86对应32位。wmic os get caption,servicepackmajorversion能同时拿到系统名称和SP主版本号用于人工核对脚本里用ver命令做快速分流。ver的输出在中文系统里会带“版本”字样但数字部分不受影响find 6.0、find 5.2、find 5.1仍然能匹配到。一个容易踩的边界Windows XP x64的ver输出也是5.2因为它和Server 2003共享NT 5.2内核。所以严格来说5.2分支里混着两种系统需要再用wmic的caption字段区分。批量部署时如果目标机里混有XP x64建议在5.2分支里加一层capation判断否则会拿Server 2003的包去装XP x64。这段脚本给的是主干逻辑生产环境请按实际机器清单补上这个分支。注意安装包文件名里的ENU代表英文语言包中文系统请替换成对应语言版本。文件名对不上时脚本会静默失败日志里什么都看不到。4. PowerShell相关报错的排查与避坑五个高频翻车现场4.1 现象装完WMF 2.0并重启SQL检查仍报“未安装”按教程装了KB968930重启了注册表里也查得到2.0SQL检查照样红叉。这是最常见也最让人怀疑人生的一种情况。原因多半是架构错位。64位SQL安装介质对应64位检查逻辑它只读64位注册表视图如果你误装了x86的WMF包版本信息写进的是WOW6432Node下的32位视图64位视图里依然干干净净。Server 2008 x64特别容易翻车因为下载页面两个架构的文件摆在一起手快就点错了。解决办法是先确认SQL安装介质架构介质文件名里通常带X64或X86标识。然后用下面两条命令分别核对两个注册表视图# 64位注册表视图SQL x64安装程序读的是这里 (Get-ItemProperty HKLM:\SOFTWARE\Microsoft\PowerShell\3\PowerShellEngine -ErrorAction SilentlyContinue).PowerShellVersion # 32位注册表视图SQL x86安装程序读的是这里 (Get-ItemProperty HKLM:\SOFTWARE\WOW6432Node\Microsoft\PowerShell\3\PowerShellEngine -ErrorAction SilentlyContinue).PowerShellVersion哪边是空、哪边有2.0一看就知道是装错还是漏装。解决动作是卸载已装的错误架构包重启再重装正确架构。这事看着像玄学本质就是注册表视图隔离。4.2 现象安装包提示“此更新不适用于您的计算机”老系统上点WMF 2.0安装包直接弹“此更新不适用于您的计算机”压根不进安装向导第一反应是包没下对。其实多数情况是前置条件没到。三类原因最常见。第一SP版本不达标XP必须是SP3Server 2003必须SP2Vista和Server 2008必须SP1及以上SP2最稳RTM版本不支持。第二顺序问题Vista/Server 2008装KB968930之前必须先装KB961501顺序反了也报同样的提示。第三语言不一致补丁包语言和系统语言对不上某些情况下也会拒绝安装。解决之前先确认SP版本一条命令wmic os get caption,servicepackmajorversion看到ServicePackMajorVersion是几心里就有数了。缺SP就先打SP再补KB961501最后装KB968930。语言方面尽量找和系统一致的包别赌“英文包在中文系统上也能跑”。4.3 现象系统里有PS 3.0/4.0SQL 2008却报缺2.0Windows 8或Server 2012自带PS 3.0机器上PowerShell用得好好的SQL 2008安装程序照样在“PowerShell 2.0”这一项打红叉。原因在SQL 2008 RTM版本的检查器逻辑上它判断的是“注册表里PowerShellVersion等于2.0”而不是“大于等于2.0”。PS 3.0把版本号写成3.0之后它认为“不等于2.0就是不满足”。这个毛病在SQL 2008后续SP补丁里才改掉集成SP2/SP3的安装介质通常不会犯。解决动作按优先级排第一选择是换SQL 2008 SP2以上集成介质让检查器和引擎版本匹配第二选择才是用规则跳过参数硬闯setup.exe /ACTIONinstall /SKIPRULESPowerShell_2_0注意/SKIPRULES后面的规则名要以安装日志里实际显示的为准不同版本拼写略有差异别凭记忆硬写。跳过规则能把安装流程走完属于“后悔药”性质——装是装上了之后在SSMS里启动PowerShell窗口、跑某些维护脚本时引擎缺失的问题还会冒出来。生产环境不建议走这条我见过同事这么干省了安装时的一小时赔了后面排查的三小时。4.4 现象规则检查过了装到一半回滚日志指向PowerShell脚本执行失败最气人的一种规则检查全绿安装进度走到80%突然回滚。翻安装日志FAILED条目清一色和PowerShell脚本调用有关。原因基本锁定在执行策略。Server 2008默认执行策略是Restricted在这种策略下任何ps1脚本都不允许执行。SQL安装向导在配置组件时要调用自己的ps1脚本结果被策略拦了组件配置没写完安装程序只能回滚。装之前先把执行策略放开Set-ExecutionPolicy RemoteSigned -Scope LocalMachineRemoteSigned的意思是本地脚本可以直接运行从外部下载的脚本必须带有效签名。对SQL安装程序来说这个级别足够不要设成Unrestricted安全基线不会放过它。装完SQL之后可以按公司安全策略改回去不过多数内部服务器就保持RemoteSigned不管了。这里还有一个域环境特例如果执行策略被组策略强制本机怎么改都会被覆盖回去先跑gpresult看有没有相关的GPO设置别在本地策略上死磕。4.5 现象注册表版本是2.0安装程序仍解析不到powershell.exe注册表检查全部通过版本号明确写着2.0SQL安装程序依然红叉日志提示找不到PowerShell引擎。原因是PATH变量里没有%SystemRoot%\System32\WindowsPowerShell\v1.0这个目录。SQL安装程序启动时会读取系统PATH在里头逐个目录找powershell.exe。常见于被安全加固脚本精简过PATH的服务器或者从远程会话里启动安装程序导致环境变量没继承全的情况。解决动作是同时检查系统级和用户级的PATH把%SystemRoot%\System32\WindowsPowerShell\v1.0加进去然后新开命令行窗口再启动安装程序。PATH改完之后老窗口里的环境变量快照不会自动刷新很多人刚改完就急着重试发现还是不行其实是窗口没换。这也解释了为什么我总习惯“改完环境变量先关窗口再开”。5. 批量扫描一批服务器的PowerShell版本先摸底再动手装SQL被PowerShell卡住这件事坑都踩过一遍之后我现在给一批老服务器装数据库前必做的一件事是用脚本把目标机全部扫一遍先知道谁缺什么、谁架构对不上再决定哪些机器要单独补包。一台台远程登录手输命令既不现实也容易漏。下面这个脚本用注册表法批量读取目标机的PowerShell版本结果直接落成CSV报告# 批量读取目标机注册表中的PowerShell版本输出CSV报告 # 前置条件目标机RemoteRegistry服务处于启动状态本机管理员有权限访问 $machines Get-Content .\machines.txt $result foreach ($m in $machines) { $path \\$m\HKLM\SOFTWARE\Microsoft\PowerShell\3\PowerShellEngine try { $ver (Get-ItemProperty $path -Name PowerShellVersion -ErrorAction Stop).PowerShellVersion [PSCustomObject]{ 主机名 $m; PowerShell版本 $ver; 状态 可读 } } catch { [PSCustomObject]{ 主机名 $m; PowerShell版本 N/A; 状态 不可读-需手工确认 } } } $result | Export-Csv .\ps_report.csv -NoTypeInformation -Encoding UTF8machines.txt每行写一个IP或主机名即可。远程读注册表走的是RemoteRegistry服务防火墙要放行135端口域环境通常无障碍工作组环境需要目标机开启远程注册表管理。状态列出现“不可读”时要么是权限不足要么是机器没开机不能直接理解成“没装PowerShell”这一点要区分开。这套方法只做粗筛命中可疑机器后再单独登录确认。想查更详细的引擎状态可以改用WinRM的Invoke-Command远程执行$PSVersionTable那套检测但老系统开WinRM要配信任主机比RemoteRegistry重得多我一般不用在普查阶段。装得多了之后我的习惯已经固定成一条链路先看注册表两处视图再决定要不要装包装完必重启重启完用检测脚本复核全部确认无误才把SQL介质交给下一环节。以前我也跳过规则硬装过后来在维护脚本上吃了亏从那以后再也不跳。这套顺序看起来多花几步但省掉的是“安装到一半回滚”这种最贵的返工。希望帮到你。本文还有配套的精品资源点击获取