ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Windows 11 中 wmic 消失?用 PowerShell CIM 替代方案全面迁移

Windows 11 中 wmic 消失?用 PowerShell CIM 替代方案全面迁移 1. 从一次真实的报错说起wmic 到底去哪了前几天帮一个朋友处理一台新装的 Windows 11 机器他习惯性地敲下wmic cpu get caption想看一眼 CPU 型号结果命令行直接甩回来一句wmic 不是内部或外部命令也不是可运行的程序或批处理文件。他当时就懵了说这命令用了十几年怎么突然就没了。其实这不是他一个人的困惑从 Windows 11 某个版本开始微软把 WMICWindows Management Instrumentation Command-line这个工具正式列入了弃用名单默认不再随系统安装。很多老运维、老脚本、老批处理文件里到处散落着 wmic 调用一旦换到新系统上整条流水线就断了。这篇文章就是冲着这个问题来的。我会把 wmic 消失的前因后果讲清楚然后给出几条真正能落地的替代路线哪些场景用 PowerShell 的 CIM 命令最合适哪些场景用原生命令行工具更省事哪些老脚本需要做兼容性改造。不管你是刚接触 Windows 命令行的新手还是维护着一堆历史脚本的老手都能从里面找到可以直接抄作业的方案。核心关键词就三个Windows 11、wmic、替代方案全文围绕它们展开不跑题。先说结论省得你翻到最后wmic 并没有被彻底删除它只是从默认安装变成了按需功能Feature on Demand你可以手动装回来但更推荐的做法是迁移到 PowerShell 的Get-CimInstance系列命令。下面我把每一步都拆开讲。2. wmic 为什么在 Windows 11 里找不到了2.1 弃用不是删除先搞清楚这个区别很多人一看到找不到命令就以为微软把 wmic 删干净了其实不是。微软的做法是把它从默认安装的组件里拿掉变成一个可选功能。这意味着两件事第一你如果确实需要可以手动装回来第二微软在释放一个明确信号——别再依赖它了早晚要迁移。这个策略微软用过很多次。比如 telnet 客户端、TFTP 客户端都是同样的套路先默认不装再慢慢从文档里淡化最后彻底移除。wmic 现在处在默认不装但还能装的阶段属于过渡期。理解这一点很关键因为它决定了你的应对策略短期可以装回来救急长期必须迁移。2.2 WMIC 被弃用的真实原因WMIC 本质上是一个命令行外壳包在 WMIWindows Management Instrumentation外面。WMI 本身是 Windows 管理体系的基石负责暴露系统硬件、操作系统、进程、服务等各类信息。WMIC 的作用就是让你在命令行里用类似 SQL 的语法去查询这些信息比如wmic process where namenotepad.exe get processid。问题出在 WMIC 的实现年代太久远。它基于老的 COM 接口输出格式固定、解析困难、对 Unicode 支持一般而且它的语法和现代 PowerShell 的管道模型格格不入。微软这些年一直在推 PowerShell 和 CIMCommon Information ModelCIM 是 WMI 的标准化、跨平台版本PowerShell 的Get-CimInstance就是它的官方入口。相比之下WMIC 就像一台还能开但配件停产的老车修起来费劲不如换新的。2.3 哪些 Windows 11 版本受影响不是所有 Windows 11 都一样。根据我的实测和社区反馈大致情况是这样的系统版本wmic 默认状态说明Windows 11 21H2默认安装早期版本还能直接用Windows 11 22H2默认安装大部分场景仍可用Windows 11 23H2部分移除部分镜像默认不装Windows 11 24H2 及以后默认不装需要手动添加Windows 11 Enterprise LTSC 2024默认不装精简镜像通常不含需要说明的是具体行为还跟你用的镜像有关。官方原版镜像、企业版、LTSC 版本、各种精简版处理方式可能不一样。我见过同一版本号一台机器有 wmic另一台没有原因就是安装源不同。所以别死记版本号直接敲命令试一下最快。3. 先救急把 wmic 装回来的两种方法3.1 用可选功能图形界面添加如果你只是想赶紧把眼前的事办了最直接的办法是通过系统设置装回来。路径是设置 → 应用 → 可选功能 → 查看更多 Windows 功能或者直接在开始菜单搜索启用或关闭 Windows 功能。在弹出的窗口里找到Windows Management Instrumentation 命令行工具英文是 WMIC勾选它确定等系统装完就行。这个方法的优点是直观不用记命令。缺点是有些精简版系统把这个入口也砍了或者列表里根本找不到这一项。遇到这种情况走下面的命令行方式。3.2 用 DISM 命令行添加功能命令行方式更可靠尤其是在服务器核心版或者没有图形界面的环境里。以管理员身份打开 PowerShell 或 CMD执行dism /online /add-capability /capabilityname:WMIC~~~~注意那个~~~~是四个波浪号不是笔误这是 DISM 功能命名的固定格式。执行完等它跑完提示成功就可以了。如果提示找不到功能说明你的系统镜像里根本没带这个包那就得考虑从对应版本的安装介质里提取或者干脆放弃装回来直接走替代方案。提示装回来只是权宜之计。微软已经明确表示 WMIC 会在未来版本中彻底移除所以别把生产脚本长期押在它身上。3.3 装回来之后的验证装完后别急着高兴先验证一下wmic os get caption正常的话会输出你的系统版本名称。如果还是报不是内部或外部命令检查一下 PATH 环境变量里有没有C:\Windows\System32\wbem这个路径。wmic.exe 就躺在这个目录下。有些系统装完功能后 PATH 没刷新重启一下命令行窗口或者注销重登就好了。4. 正解用 PowerShell CIM 命令全面替代 wmic4.1 为什么首选 Get-CimInstance替代 wmic 的方案有好几种但我最推荐的是 PowerShell 的Get-CimInstance。理由有三条第一它是微软官方主推的方向未来不会突然消失第二它返回的是结构化对象不是一堆文本后续处理、筛选、导出都方便得多第三它跨平台同样的思路在 PowerShell 7 上也能用甚至能连远程机器的 CIM。很多人对 PowerShell 有畏难情绪觉得语法复杂。其实你只要掌握把 wmic 的查询翻译成 CIM 类名 筛选条件这个套路大部分场景都能覆盖。下面我把最常见的几类 wmic 用法逐一翻译。4.2 硬件信息查询的对照翻译先看最经典的 CPU 查询。老写法是wmic cpu get caption新写法是Get-CimInstance -ClassName Win32_Processor | Select-Object -Property NameWin32_Processor就是对应的 CIM 类Name属性对应原来的 caption。如果你想要更多信息比如核心数、主频直接加属性名就行Get-CimInstance -ClassName Win32_Processor | Select-Object Name, NumberOfCores, MaxClockSpeed内存查询也是同理。老写法wmic memorychip get capacity新写法Get-CimInstance -ClassName Win32_PhysicalMemory | Select-Object Capacity, Speed, Manufacturer这里有个坑要注意Capacity返回的是字节数一大串数字看着头疼。想转成 GB可以这样Get-CimInstance -ClassName Win32_PhysicalMemory | ForEach-Object { [math]::Round($_.Capacity / 1GB, 2) }4.3 系统与操作系统信息查询查系统版本老写法wmic os get caption, version新写法Get-CimInstance -ClassName Win32_OperatingSystem | Select-Object Caption, Version, BuildNumber查系统启动时间老写法wmic os get lastbootuptime新写法(Get-CimInstance -ClassName Win32_OperatingSystem).LastBootUpTime查 BIOS 信息老写法wmic bios get serialnumber新写法Get-CimInstance -ClassName Win32_BIOS | Select-Object SerialNumber, Manufacturer, Version这些翻译有个通用规律wmic 里的别名比如 os、bios、cpu对应到 CIM 里就是完整的类名Win32_OperatingSystem、Win32_BIOS、Win32_Processor。你只要记住这个映射关系剩下的就是查属性名。4.4 进程与服务管理的替代写法进程查询是运维里用得最多的。老写法wmic process where namenotepad.exe get processid新写法有两种看你的习惯Get-CimInstance -ClassName Win32_Process -Filter Namenotepad.exe | Select-Object ProcessId, Name或者用 PowerShell 原生的Get-Process更简洁Get-Process -Name notepad | Select-Object Id, Name服务查询老写法wmic service where namewuauserv get state新写法Get-CimInstance -ClassName Win32_Service -Filter Namewuauserv | Select-Object Name, State, StartMode或者用原生的Get-Service -Name wuauserv | Select-Object Name, Status, StartType这里我要多说一句能用原生 cmdlet比如Get-Process、Get-Service就优先用它们比 CIM 更快、更符合 PowerShell 习惯。CIM 主要用在原生 cmdlet 覆盖不到的场景比如查主板、查物理内存条。4.5 一个完整的迁移对照表为了让你查起来方便我把最常见的 wmic 命令和替代方案整理成表老 wmic 命令新 PowerShell 替代备注wmic cpu get captionGet-CimInstance Win32_Processor | Select Name查 CPUwmic memorychip get capacityGet-CimInstance Win32_PhysicalMemory | Select Capacity查内存wmic os get captionGet-CimInstance Win32_OperatingSystem | Select Caption查系统wmic bios get serialnumberGet-CimInstance Win32_BIOS | Select SerialNumber查序列号wmic process get name,processidGet-Process | Select Name, Id查进程wmic service get name,stateGet-Service | Select Name, Status查服务wmic logicaldisk get size,freespaceGet-CimInstance Win32_LogicalDisk | Select DeviceID, Size, FreeSpace查磁盘wmic product get nameGet-CimInstance Win32_Product | Select Name查已装软件wmic startup get captionGet-CimInstance Win32_StartupCommand | Select Caption查启动项wmic useraccount get nameGet-CimInstance Win32_UserAccount | Select Name查用户注意Win32_Product这个类要慎用。查询它会触发 MSI 重新配置在大批量机器上跑可能导致性能问题甚至意外修复软件。查已安装软件更推荐读注册表后面会讲。5. 不写 PowerShell 也能干活原生命令行替代方案5.1 systeminfo 和 driverquery 这类老牌工具不是所有场景都需要 PowerShell。有些信息用系统自带的原生命令反而更快。比如查系统概要systeminfo一条命令就能输出一堆信息虽然格式是文本但胜在不用记类名systeminfo | findstr /C:OS Name /C:OS Version查驱动列表用driverquerydriverquery /v查磁盘分区用diskpart或者fsutil。这些工具都是系统自带的不依赖 wmic也不依赖 PowerShell在批处理脚本里调用特别方便。5.2 用 reg query 查注册表信息很多原来用 wmic 查的信息其实注册表里都有而且reg query这个命令从 Windows 2000 时代就有稳定性没得说。比如查系统版本reg query HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion /v ProductName reg query HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion /v DisplayVersion查已安装软件列表比 Win32_Product 安全得多reg query HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall /s /v DisplayName这个方法的缺点是输出格式需要自己解析但如果你只是想在批处理里判断某个软件装没装用findstr过滤一下就够了。5.3 tasklist 和 sc 命令的妙用进程和服务这两块其实根本不需要 wmic。查进程用tasklisttasklist /FI IMAGENAME eq notepad.exe查服务用scsc query wuauservsc命令还能启动、停止、配置服务功能比 wmic 还全。我见过很多老脚本用 wmic 去启停服务其实换成sc更直接sc stop wuauserv sc start wuauserv5.4 什么时候该用原生命令什么时候该上 PowerShell这里给个简单的判断标准。如果你只是临时查一下信息或者写的是简单的批处理原生命令够用就用原生命令启动快、依赖少。如果你需要做条件判断、循环处理、格式化输出、导出 CSV 或 JSON那就上 PowerShell它的对象模型能省你大量解析文本的功夫。我个人的习惯是一次性排查用原生命令写成脚本长期跑用 PowerShell。这个分界线不是绝对的但能帮你快速做决定。6. 老脚本迁移实战把 wmic 调用逐个换掉6.1 先做一次全盘扫描找出所有 wmic 调用迁移的第一步不是改代码是搞清楚你的脚本库里到底有多少地方用了 wmic。在脚本目录下跑一条命令Get-ChildItem -Path . -Recurse -Include *.bat,*.cmd,*.ps1 | Select-String -Pattern wmic | Select-Object Path, LineNumber, Line这条命令会把所有 .bat、.cmd、.ps1 文件里出现 wmic 的行都列出来包括行号和具体内容。有了这份清单你才知道工作量有多大。我见过一个运维朋友以为就三五个脚本用了 wmic一扫发现四十多个差点没崩溃。早扫描早安心。6.2 批处理脚本里的替换策略批处理里调用 wmic 通常是为了拿一个值赋给变量比如for /f tokens2 delims %%a in (wmic os get caption /value) do set OSNAME%%a这种写法迁移起来最麻烦因为要改成调用 PowerShell 再解析输出。可以这样改for /f delims %%a in (powershell -NoProfile -Command (Get-CimInstance Win32_OperatingSystem).Caption) do set OSNAME%%a注意-NoProfile这个参数它能跳过 PowerShell 配置文件的加载启动更快也更不容易受环境影响。这个细节很多教程不讲但在批处理里调用 PowerShell 时非常关键不加的话可能慢好几秒。6.3 PowerShell 脚本里的替换PowerShell 脚本里如果还在用 wmic那基本就是历史遗留。直接换成 CIM 命令即可而且换完之后你会发现代码更短了。比如原来$cpu wmic cpu get name /value | Select-String Name换成$cpu (Get-CimInstance Win32_Processor).Name一行搞定还不用做字符串切割。这就是对象模型的好处。6.4 迁移后的回归测试要点改完脚本别急着上线一定要做回归测试。重点测这几个方面输出格式是否和原来一致如果下游有程序解析你的输出格式变了会出大事、异常情况是否处理比如查不到信息时返回什么、权限是否够用有些 CIM 类需要管理员权限。我踩过的坑是原来 wmic 在普通权限下能查的信息换成 CIM 后某些类需要提权结果脚本在计划任务里跑就失败了。所以测试时一定要用实际运行脚本的那个账户去测。7. 常见问题与排查技巧实录7.1 高频问题速查表问题现象可能原因解决方法wmic 不是内部或外部命令系统未安装 WMIC 功能用 DISM 添加或改用 CIMGet-CimInstance 报拒绝访问权限不足以管理员身份运行CIM 查询返回空类名或属性名写错用 Get-CimClass 查类用 Get-Member 查属性批处理调用 PowerShell 很慢加载了配置文件加 -NoProfile 参数Win32_Product 查询卡住触发 MSI 重配置改用注册表查询远程 CIM 连接失败防火墙或 WinRM 未配置检查 WinRM 服务和防火墙规则7.2 怎么快速找到正确的 CIM 类名和属性名这是新手最头疼的问题知道要查什么但不知道类名。两个技巧。第一用Get-CimClass模糊搜索Get-CimClass -ClassName *Processor*它会列出所有名字里带 Processor 的类你一眼就能找到 Win32_Processor。第二找到类之后用Get-Member看它有哪些属性Get-CimInstance Win32_Processor | Get-Member -MemberType Property这两个命令组合起来基本能解决 90% 的不知道查什么的问题。我刚开始学 CIM 的时候就是靠这两招摸清门路的。7.3 输出格式处理的几个坑CIM 返回的对象直接输出到控制台时格式和 wmic 的文本输出完全不同。如果你有下游程序依赖特定格式需要手动格式化。比如要输出成keyvalue的形式Get-CimInstance Win32_OperatingSystem | ForEach-Object { Caption$($_.Caption) }要导出 CSVGet-CimInstance Win32_LogicalDisk | Select-Object DeviceID, Size, FreeSpace | Export-Csv -Path disks.csv -NoTypeInformation -Encoding UTF8-Encoding UTF8这个参数别省不然中文系统下导出的 CSV 用 Excel 打开会乱码。这个坑我踩过不止一次。7.4 几个只有踩过才知道的经验第一Get-CimInstance默认走的是 WSMan 协议比老的 DCOM 快但需要 WinRM 服务在跑。如果目标机器 WinRM 没开可以加-ComputerName时配合-SessionOption指定用 DCOM不过速度会慢一些。第二查大量数据时比如遍历几千个进程CIM 查询可能比原生 cmdlet 慢。这时候优先用Get-Process、Get-Service这类原生命令它们底层做了优化。第三如果你在 32 位 PowerShell 里跑 CIM 查询某些类可能查不到 64 位的信息。确保用 64 位 PowerShell路径是C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe而不是 SysWOW64 下面那个。第四写脚本时给 CIM 查询加上-ErrorAction Stop这样出错时能被 try/catch 捕获而不是默默返回空值。默默失败是脚本调试里最烦人的问题。8. 面向未来的建议把 CIM 当成默认选择8.1 新脚本一律用 CIM别再碰 wmic如果你现在开始写新脚本没有任何理由再用 wmic。CIM 命令更清晰、更强大、更面向未来。哪怕你现在的机器上 wmic 还能用也别用因为迁移成本会随着脚本数量增长而指数级上升。我见过太多团队因为现在还能用而拖延迁移结果某次系统升级后集体翻车连夜改脚本。8.2 给团队定一个迁移时间表如果你是团队里负责运维规范的人建议定一个明确的迁移截止日期。比如三个月内所有新脚本必须用 CIM六个月内完成存量脚本迁移。迁移过程中把常见 wmic 到 CIM 的对照表沉淀成团队文档新人直接查表就行不用重新摸索。这个投入是一次性的收益是长期的。8.3 关注 Windows 11 后续版本的变化Windows 11 的更新节奏比较快26H2 之类的版本会陆续到来。每次大版本更新后建议在测试机上跑一遍你的关键脚本确认没有因为组件移除而失效。这个习惯不只为 wmic对所有依赖系统组件的脚本都适用。我个人的做法是维护一个关键脚本冒烟测试清单系统更新后花十分钟跑一遍比出事后再排查省心得多。最后分享一个我自己的小习惯在每台新装的 Windows 11 机器上第一件事就是敲一遍Get-CimInstance Win32_OperatingSystem | Select Caption, Version确认 CIM 通道正常。这个动作花不了几秒钟但能让你在后续所有运维操作里心里有底。wmic 的时代正在落幕CIM 的时代早就开始了早点上车少踩坑。
返回列表