已弃用的 wmic 的 cmd / batch 替代品是什么?

What's the cmd / batch alternative to the deprecated wmic?

我知道 wmic 自 2012 年起已被弃用,我现在通常使用 PowerShell,所以已经放弃了。

但是,我经常遇到需要在批处理文件中工作但无法将解决方案迁移到 PowerShell 的选项。

我的问题是:wmic 已弃用,推荐的替代方法是从命令提示符和批处理文件继续访问 Windows Management Instrumentation?

我目前能想到的最好的是:

powershell -command "(Get-CimInstance Win32_Processor) | select *" | some_other_program.exe

(本例获取处理器属性)

但它的一个主要缺点是错误级别和环境不再可访问。也就是说,powershell 命令成功完成,即使该命令没有成功)。并且在 powershell 命令中对环境所做的更改不会传播到批处理文件。

欢迎就如何具体解决这些问题或从批处理调用 powershell 以访问 WMI 的更好替代方法提出任何建议,但具体来说,我想知道如何 运行 powershell 命令并访问标准输出以外的结果。

But one major downside of that is that errorlevels and the environment are no longer accessible.

通过 PowerShell CLI 调用 PowerShell 命令的最简单方法(Windows PowerShell 中的powershell.exepwsh在 PowerShell (Core) 7+) 报告非零退出代码 引发脚本终止(线程终止)错误,这会导致错误代码 1 - 您的批处理文件可以测试的错误代码:

@echo off

:: # Simulate a failing CIM call
powershell -c "$ErrorActionPreference='Stop'; Get-CimInstance Win32_NoSuchClass" 

:: # Exit, if the PowerShell command failed.
if ERRORLEVEL 1 echo Error: Get-CimInstance failed>&2 & exit /b %ERRORLEVEL%

echo Moving on...

$ErrorActionPreference='Stop' 在命令的开头确保任何后续错误都会成为脚本终止错误。
要有选择地忽略非终止错误,请单独使用 -ErrorAction Ignore 命令。
如果没有错误发生,则退出代码隐式为 0.

PowerShell 的错误处理非常复杂;有关综合摘要,请参阅 this GitHub issue

注意:

  • Get-CimInstance 等本机 PowerShell 命令不设置退出代码;您能做的最好的事情就是将错误映射到退出代码 1,并将成功映射到退出代码 0.

  • 如果您从 PowerShell 调用外部程序,它们的退出代码将反映在自动变量中 $LASTEXITCODE;您可以使用 exit $LASTEXITCODE 从 PowerShell 命令字符串传递该退出代码;但是,您通常可以直接从批处理文件中直接调用外部程序 - 无需通过 PowerShell 绕道。


And changes made to the environment in the powershell command do not propagate to the batch file.

是的,PowerShell 命令总是在 子进程 中运行,其环境对调用进程没有影响。

一般:

  • 从文件中的 PowerShell 命令捕获 输出 或使用 for /f 循环在内存中处理它(参见下面的示例)- 除非通过输出 through 就足够了。

  • 如果您确实需要修改调用批处理文件的 environment,让 PowerShell 命令输出 data这些修改,并将它们应用到批处理文件中。

    • 例如,如果您希望 PowerShell 命令设置环境变量,请使其输出 <name>=<value> 个字符串对,批处理文件可使用这些字符串对设置这些变量。

使用 for /f 定制用于在批处理文件中解析的 PowerShell 命令输出的示例;请注意,引用可能会变得棘手:

@echo off

:: # Get the .Name and .MaxClockSpeed property values from the Win32_Processor instance.
for /f "tokens=1,* delims==" %%i in ('powershell -c "$ErrorActionPreference='Stop'; Get-CimInstance Win32_Processor | %% { foreach ($n in 'Name', 'MaxClockSpeed') { \""$n=$($_.$n)\"" } }"') do (
  echo [%%i]=[%%j]
)

:: # Exit, if the PowerShell command failed.
if ERRORLEVEL 1 echo Error: Get-CimInstance failed>&2 & exit /b %ERRORLEVEL%

上面的结果类似于:

[Name]=[Intel(R) Core(TM) i5-7360U CPU @ 2.30GHz]
[MaxClockSpeed]=[2304]