简介:这份资源面向在 Windows 11 环境下使用 VMware vSphere 的运维人员与虚拟化学习者,提供 VMware PowerCLI 的完整安装包,帮助解决自动化管理工具部署与脚本调用的问题。压缩包共约 2000 个文件,整体 143.15MB,以 871 个 ps1 脚本、112 个 psd1 模块清单、66 个 psm1 模块文件为核心,辅以 237 个 dll 运行库、135 个 xml 配置、68 个 cat 签名文件及 json、md 等说明文档,覆盖存储管理、SDK 运行时、vSphere 应用本地账户管理、vCenter 模板与可信基础架构等模块。已有 237 人学习下载。安装后可在 PowerShell 中通过 Get-Module VMware* 验证模块加载,并借助 cmdlet 完成虚拟机创建配置、网络与存储资源管理、环境健康监控等自动化任务,也可与 Ansible、Puppet 等工具集成,适合希望提升运维效率、构建大规模自动化编排方案的系统管理员参考使用。
1. 在 Windows 11 上装 VMware PowerCLI:为什么你照着官方文档走反而会翻车
很多人第一次在 Windows 11 上装 VMware PowerCLI,都是打开 PowerShell 敲一句Install-Module VMware.PowerCLI,然后等着进度条跑完。结果要么卡在「正在解析依赖项」,要么装完Connect-VIServer直接报模块找不到,要么 PowerShell 7 和 Windows PowerShell 5.1 里装到了两个不同的地方,互相看不见。这不是你手气差,而是 Windows 11 默认的 PowerShell 执行策略、PSGallery 源配置、以及 PowerShell 5.1 与 7.x 并存这三件事叠在一起造成的。
这篇笔记要解决的就是:在 Windows 11 上把 VMware PowerCLI 装到「能稳定连上 vCenter、能批量跑脚本、重启后不失效」的程度。适合两类人——刚接手虚拟化运维、需要在本地做自动化巡检的工程师,以及已经会用 PowerCLI 但每次换机器都要重新踩一遍坑的老手。下面从环境判断讲到模块安装、再到连接验证和批量脚本落地,每一步都给可复制的命令和参数说明。
2. 装之前先搞清楚:PowerCLI 到底装在哪、用哪个 PowerShell 跑
2.1 PowerShell 5.1 和 PowerShell 7 的模块目录不是同一个
Windows 11 自带的是 Windows PowerShell 5.1,路径在C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe,它的模块目录是C:\Program Files\WindowsPowerShell\Modules和C:\Users\<你>\Documents\WindowsPowerShell\Modules。而 PowerShell 7.x 是独立安装的,模块目录在C:\Program Files\PowerShell\7\Modules和C:\Users\<你>\Documents\PowerShell\Modules。
这两个目录互不通用。你在 PowerShell 7 里Install-Module,模块默认落到 7 的目录,回到 5.1 里Get-Module -ListAvailable VMware.PowerCLI就是空的。反过来也一样。所以第一件事是决定用哪个宿主,然后所有安装、连接、脚本执行都在同一个宿主里做,别混着来。
我一般建议用 PowerShell 7.x,因为 PowerCLI 12 以后对 7.x 支持更好,并行处理和 JSON 输出也更顺。但如果你要调一些老的 .NET 组件或者公司内部只签了 5.1 的脚本,那就统一用 5.1,别两边都装。
判断当前宿主和版本:
# 查看当前 PowerShell 版本和宿主路径 $PSVersionTable.PSVersion (Get-Process -Id $PID).Path # 查看当前会话能看到的模块目录 $env:PSModulePath -split ';'$PSVersionTable.PSVersion告诉你主版本号,5 开头就是 Windows PowerShell,7 开头就是 PowerShell 7。(Get-Process -Id $PID).Path直接给出当前进程的可执行文件路径,比猜更可靠。$env:PSModulePath是模块搜索路径,安装前先看一眼,能避免「装完了却找不到」的玄学。
2.2 执行策略和 TLS 版本是两个必查项
Windows 11 默认执行策略是Restricted,不允许运行任何脚本,Install-Module在某些情况下也会被拦。另外 PowerShell 5.1 默认可能还在用 TLS 1.0 去连 PSGallery,而 PSGallery 早就要求 TLS 1.2 了,这会导致「无法连接到源」或者下载到一半断掉。
先查再改:
# 查看当前执行策略 Get-ExecutionPolicy -List # 查看当前会话的 TLS 版本 [Net.ServicePointManager]::SecurityProtocol如果CurrentUser那一行是Undefined或Restricted,就改成RemoteSigned,意思是本地脚本随便跑,从网上下载的脚本要有签名。这个粒度比直接Unrestricted安全,也比AllSigned省事。
# 只对当前用户生效,不需要管理员权限 Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser # 强制当前会话使用 TLS 1.2 [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12-Scope CurrentUser是关键,它只改当前用户的策略,不动系统全局,也不需要管理员权限,出问题好回退。TLS 那行只对当前会话生效,所以如果你打算长期用,得写进$PROFILE,这个后面讲。
2.3 确认 PSGallery 源可用并信任它
PowerCLI 不在 Windows 自带源里,得从 PowerShell Gallery 拉。先确认源存在且地址正确:
# 列出已注册的 PSRepository Get-PSRepository # 如果 PSGallery 没注册或地址不对,重新注册 Register-PSRepository -Default -ErrorAction SilentlyContinue # 把 PSGallery 标记为受信任,避免每次安装都弹确认 Set-PSRepository -Name PSGallery -InstallationPolicy TrustedGet-PSRepository会显示 Name、SourceLocation、InstallationPolicy 三列。如果InstallationPolicy是Untrusted,Install-Module会交互式问你「是否继续」,在自动化脚本里就卡住了。Set-PSRepository把它设成Trusted之后就一路畅通。这一步不是必须,但在批量部署或 CI 环境里是省心操作。
3. 把 VMware PowerCLI 装进 Windows 11:三种装法和参数怎么选
3.1 在线安装:Install-Module 的四个关键参数
最常用的方式就是从 PSGallery 在线装。但直接Install-Module VMware.PowerCLI有几个默认行为要注意:它默认只装当前用户、默认会弹确认、默认不覆盖已存在的版本。生产环境里我一般显式写全参数:
# 在线安装 PowerCLI,显式指定作用域和确认策略 Install-Module -Name VMware.PowerCLI ` -Scope CurrentUser ` -AllowClobber ` -Force ` -Confirm:$false # 查看装完的版本 Get-Module -ListAvailable VMware.PowerCLI | Select-Object Name, Version, Path-Scope CurrentUser装到用户目录,不需要管理员权限,也不会污染系统目录。-AllowClobber允许覆盖同名命令,PowerCLI 里有些 cmdlet 名字和系统命令冲突,不加这个会报「命令已存在」。-Force和-Confirm:$false一起用,跳过所有交互确认,适合脚本化。Get-Module -ListAvailable后面的Select-Object是为了看清版本和路径,确认装到了你预期的宿主里。
如果网络慢或者 PSGallery 抽风,可以加-SkipPublisherCheck,但这是把双刃剑——它跳过发布者签名校验,只在确认源可信时用。
3.2 离线安装:Save-Module 加手动拷贝的完整流程
内网机器连不上 PSGallery 是常态。做法是在一台能上网的机器上把模块存下来,再拷到目标机。注意 PowerCLI 是一组模块的集合,不是单个模块,所以要用Save-Module指定VMware.PowerCLI,它会连带依赖一起拉。
# 在能上网的机器上,把模块和依赖存到本地目录 Save-Module -Name VMware.PowerCLI -Path D:\offline\powercli -Force # 查看存下来的内容 Get-ChildItem D:\offline\powercli -Directory | Select-Object NameSave-Module不会安装,只下载。-Path指定存放根目录,每个模块会建一个子目录。下载完把整个powercli目录拷到目标机的用户模块目录,比如C:\Users\<你>\Documents\PowerShell\Modules,然后在新机器上验证:
# 目标机上确认模块可见 Get-Module -ListAvailable VMware.PowerCLI | Select-Object Name, Version # 如果看不到,手动把路径加进 PSModulePath $env:PSModulePath = "C:\Users\<你>\Documents\PowerShell\Modules;" + $env:PSModulePath手动加PSModulePath只对当前会话有效。要长期生效,得用[Environment]::SetEnvironmentVariable写用户级环境变量,或者干脆把模块放到已经在搜索路径里的目录。离线安装最容易翻车的地方就是依赖没拷全,Save-Module默认会拉依赖,但如果你手动只拷了VMware.PowerCLI一个目录,运行时就会报缺VMware.VimAutomation.Core之类的错。
3.3 版本锁定与降级:什么时候不该装最新版
PowerCLI 版本和 vCenter 版本有兼容矩阵。新版本 PowerCLI 通常能连老 vCenter,但老版本 PowerCLI 连新 vCenter 可能缺 API。反过来,如果你脚本里用了某个已被移除的 cmdlet,升级后直接报错。所以生产环境里我倾向于锁版本,而不是无脑最新。
# 查看可用的历史版本 Find-Module -Name VMware.PowerCLI -AllVersions | Select-Object Version, PublishedDate | Sort-Object PublishedDate -Descending | Select-Object -First 10 # 安装指定版本 Install-Module -Name VMware.PowerCLI -RequiredVersion 13.0.0.21624300 ` -Scope CurrentUser -AllowClobber -ForceFind-Module -AllVersions列出所有可用版本和发布时间,方便你对照 vCenter 版本选。-RequiredVersion精确锁定版本,注意它和-MinimumVersion不同,前者是精确匹配。如果已经装了新版想降级,先卸载再装:
# 卸载当前用户下的 PowerCLI Get-InstalledModule -Name VMware.PowerCLI | Uninstall-Module -Force # 再装指定版本 Install-Module -Name VMware.PowerCLI -RequiredVersion 13.0.0.21624300 ` -Scope CurrentUser -AllowClobber -ForceGet-InstalledModule只列通过Install-Module装的模块,手动拷进去的它看不到,那种得直接删目录。卸载时如果提示有其他模块依赖,加-Force会一起处理,但要清楚自己在删什么。
4. 装完不算完:连接 vCenter 前的配置和验证步骤
4.1 关掉 CEIP 和证书警告,让脚本能无人值守跑
PowerCLI 首次连接会弹客户体验改进计划(CEIP)提示,还会因为 vCenter 自签证书弹证书警告。这两样在交互式用没问题,在脚本里就是灾难。装完先做三件事:
# 关闭客户体验改进计划 Set-PowerCLIConfiguration -Scope User -ParticipateInCEIP $false -Confirm:$false # 设置证书动作为忽略,仅限测试环境 Set-PowerCLIConfiguration -Scope User -InvalidCertificateAction Ignore -Confirm:$false # 设置默认服务器模式,避免每次连都问 Set-PowerCLIConfiguration -Scope User -DefaultVIServerMode Multiple -Confirm:$false-Scope User表示只影响当前用户,不动系统级配置。-ParticipateInCEIP $false关掉遥测。-InvalidCertificateAction Ignore是让自签证书不弹警告,生产环境更稳妥的做法是把 vCenter 证书导入受信任根,而不是全局 Ignore,这里按测试环境写。-DefaultVIServerMode Multiple允许同时连多个 vCenter,做跨站点巡检时有用。
4.2 用 Connect-VIServer 验证安装是否真的成功
配置完就该验证了。最直接的验证不是Get-Module,而是真的连一次 vCenter 并拉一条数据:
# 连接 vCenter,凭据用交互式输入 $cred = Get-Credential Connect-VIServer -Server vcenter.example.local -Credential $cred # 拉取所有虚拟机名称和电源状态,验证 API 通路 Get-VM | Select-Object Name, PowerState, NumCpu, MemoryGB | Format-Table -AutoSize # 断开连接 Disconnect-VIServer -Server * -Confirm:$falseGet-Credential弹窗输入,避免密码写进脚本历史。Connect-VIServer的-Server可以是 IP 或域名,域名要能解析。Get-VM能返回数据,说明模块加载、认证、API 调用整条链路都通了。Disconnect-VIServer -Server *断开所有连接,-Confirm:$false跳过确认。如果Get-VM报「未连接到服务器」,八成是Connect-VIServer那步就失败了,往上翻错误信息看是认证问题还是网络问题。
4.3 把配置写进 $PROFILE,重启后不用重来
前面那些Set-PowerCLIConfiguration是持久化的,但 TLS 版本和PSModulePath的临时修改不是。要让每次开 PowerShell 都自动就绪,写进$PROFILE:
# 查看当前宿主的 profile 路径 $PROFILE.CurrentUserAllHosts # 如果文件不存在就创建 if (-not (Test-Path $PROFILE.CurrentUserAllHosts)) { New-Item -Path $PROFILE.CurrentUserAllHosts -ItemType File -Force } # 追加 TLS 和模块路径设置 Add-Content -Path $PROFILE.CurrentUserAllHosts -Value @' [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 Import-Module VMware.PowerCLI -ErrorAction SilentlyContinue '@$PROFILE.CurrentUserAllHosts对当前用户的所有宿主生效,比$PROFILE覆盖面广。Add-Content追加而不是覆盖,避免把已有配置冲掉。Import-Module加-ErrorAction SilentlyContinue是为了在模块没装时不报错,保持 profile 干净。注意 profile 里的Import-Module会拖慢启动速度,如果你更在意启动快,可以去掉这行,改成用的时候再手动导入。
5. 避坑与排查:Windows 11 装 PowerCLI 最常见的五个翻车现场
5.1 报「无法解析源」或「找不到与参数名称匹配的参数」
现象:Install-Module直接报Unable to resolve package source或者A parameter cannot be found that matches parameter name 'AllowClobber'。
原因:前者是 PSGallery 没注册或 TLS 版本太低;后者通常是你把Install-Module和Install-Package搞混了,或者 PowerShellGet 版本太老不支持这个参数。
解决:先Get-PSRepository确认源在,不在就Register-PSRepository -Default。再确认 TLS 是 1.2。如果是参数不识别,升级 PowerShellGet:Install-Module PowerShellGet -Force -AllowClobber,然后重开宿主再试。
5.2 装完了但 Get-Module 看不到
现象:Install-Module显示成功,但Get-Module -ListAvailable VMware.PowerCLI返回空。
原因:装到了另一个宿主的模块目录。比如你在 PowerShell 7 里装的,现在用 5.1 查,自然看不到。
解决:用(Get-Process -Id $PID).Path确认当前宿主,然后$env:PSModulePath -split ';'看搜索路径。要么切到对应宿主,要么把模块目录手动加进PSModulePath。长期方案是统一用一个宿主。
5.3 Connect-VIServer 卡住或报证书错误
现象:Connect-VIServer长时间无响应,或者报The remote certificate is invalid。
原因:证书不受信任,或者网络到 vCenter 的 443 端口不通。
解决:测试环境先Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Confirm:$false。生产环境应该把 vCenter 证书导入受信任根。网络问题用Test-NetConnection vcenter.example.local -Port 443确认端口通不通,不通就是防火墙或 DNS 的事,跟 PowerCLI 无关。
5.4 脚本在 5.1 能跑,在 7 里报错
现象:同一个脚本,Windows PowerShell 5.1 正常,PowerShell 7 报语法或 cmdlet 找不到。
原因:PowerShell 7 基于 .NET Core,部分老模块和 .NET Framework 专有 API 不兼容。另外 7 默认启用严格模式,一些在 5.1 里被容忍的写法会报错。
解决:先确认 PowerCLI 版本是否支持 7.x,老版本可能只支持 5.1。然后在 7 里用$Error[0] | Format-List * -Force看完整错误。如果是严格模式问题,检查变量是否未初始化就使用。实在不行就统一回 5.1,别跟兼容性较劲。
5.5 重启后配置全丢了
现象:装完当天能用,第二天开机Connect-VIServer又弹 CEIP 和证书警告。
原因:Set-PowerCLIConfiguration的-Scope User是持久化的,但如果你当时用的是-Scope Session,就只对当前会话有效。另外 TLS 和PSModulePath的临时修改本来就不持久。
解决:确认配置时用的是-Scope User,用Get-PowerCLIConfiguration查看当前生效值。TLS 和模块导入写进$PROFILE。如果还是丢,检查是不是有组策略或安全软件在重置用户配置。
6. 从单机验证到批量巡检:一个能直接改的 PowerCLI 脚本骨架
装好之后,真正体现价值的是批量操作。下面这个骨架做的是:连多个 vCenter、拉所有虚拟机、筛出快照超过 7 天的、导出 CSV。你可以直接改参数用。
# 批量巡检脚本骨架:多 vCenter、快照超期检查、导出 CSV param( [string[]]$VIServers = @("vcenter01.example.local", "vcenter02.example.local"), [int]$SnapshotAgeDays = 7, [string]$OutputPath = "D:\reports\snapshot_report_$(Get-Date -Format 'yyyyMMdd').csv" ) # 确保输出目录存在 $outDir = Split-Path $OutputPath -Parent if (-not (Test-Path $outDir)) { New-Item -Path $outDir -ItemType Directory -Force | Out-Null } $cred = Get-Credential -Message "输入 vCenter 凭据" $results = foreach ($vc in $VIServers) { try { Connect-VIServer -Server $vc -Credential $cred -ErrorAction Stop # 拉取所有虚拟机及其快照 Get-VM | Get-Snapshot | Where-Object { $_.Created -lt (Get-Date).AddDays(-$SnapshotAgeDays) } | Select-Object @{N='vCenter';E={$vc}}, VM, Name, Created, SizeGB } catch { Write-Warning "连接 $vc 失败: $($_.Exception.Message)" } finally { Disconnect-VIServer -Server $vc -Confirm:$false -ErrorAction SilentlyContinue } } # 导出并显示摘要 $results | Export-Csv -Path $OutputPath -NoTypeInformation -Encoding UTF8 Write-Host "共发现 $($results.Count) 个超期快照,报告已写入 $OutputPath"param块把 vCenter 列表、快照天数阈值、输出路径都参数化,改起来不用动逻辑。Get-Credential只弹一次,多个 vCenter 复用同一套凭据,前提是这些 vCenter 用同一套认证源。try/catch/finally保证单个 vCenter 连不上不会中断整个巡检,finally里的Disconnect-VIServer确保连接被释放,避免会话堆积。Get-Snapshot的Created属性和(Get-Date).AddDays(-$SnapshotAgeDays)比较,筛出超期快照。Export-Csv用-Encoding UTF8避免中文乱码,-NoTypeInformation去掉多余的#TYPE行。
几个可以调的参数:$SnapshotAgeDays按你的保留策略改,常见是 3 到 14 天。$VIServers可以改成从文件读,比如Get-Content D:\vcenters.txt。如果 vCenter 数量多,foreach可以换成ForEach-Object -Parallel,但要注意 PowerCLI 的会话在并行里不共享,每个线程得自己Connect-VIServer。
验证脚本是否正常,先拿一个 vCenter 跑,确认 CSV 有数据、字段对得上,再扩到全部。我自己的习惯是每次改完脚本先-WhatIf跑一遍——虽然这个骨架没实现-WhatIf,但你可以给Disconnect-VIServer和Export-Csv这类有副作用的操作加-WhatIf支持,用[CmdletBinding(SupportsShouldProcess)]声明。这个习惯救过我很多次,尤其是脚本里带删除或修改操作的时候。
最后说一个我踩过的坑:别在 profile 里Import-Module所有 PowerCLI 子模块,启动会慢到让你怀疑人生。按需导入,或者干脆不导入,用的时候再Import-Module VMware.PowerCLI。希望帮到你。
本文还有配套的精品资源,点击获取