[我知道wmic
自2012年起就已弃用,现在无论如何我通常都使用PowerShell,因此已经离开它了。
但是,我经常遇到需要在批处理文件中工作并且无法将解决方案迁移到PowerShell的情况。
我的问题是:不建议使用wmic
,从命令提示符和批处理文件继续访问Windows Management Instrumentation的推荐替代方法是什么?
我目前能想到的最好的方法是:
powershell -command "(Get-CimInstance Win32_Processor) | select *" | some_other_program.exe
(此示例获取处理器属性)
但是其中一个主要缺点是错误级别和环境不再可用。也就是说,即使该命令没有成功,powershell命令也会成功完成。并且在powershell命令中对环境所做的更改不会传播到批处理文件。
欢迎提供任何有关如何专门解决这些问题的建议,或者关于从批处理中调用Powershell来访问WMI的更好的选择,但是特别地,我想知道如何运行powershell命令并访问结果,而不是标准输出。
但是其中一个主要缺点是错误级别和环境不再可用。
使通过PowerShell CLI调用PowerShell命令报告非零退出代码的最简单方法是引发脚本终止(线程终止)错误,该错误会导致错误代码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以获取全面摘要。
注:
PowerShell本地命令,例如Get-CimInstance
,未设置退出代码;最好的办法是将错误映射到退出代码1
,将成功映射到退出代码0
。
如果从PowerShell调用外部程序,则它们的退出代码将反映在自动变量$LASTEXITCODE
中;您可以使用exit $LASTEXITCODE
从PowerShell命令字符串传递该退出代码;但是,您通常可以直接从批处理文件中直接调用外部程序-无需通过PowerShell绕行。
并且在powershell命令中对环境所做的更改不会传播到批处理文件。
确实,PowerShell命令总是在子进程中运行,其环境对调用进程没有影响。
一般:
从文件中的PowerShell命令捕获[[输出或通过for /f
循环在内存中对其进行处理(请参见下面的示例)-除非传递输出[[through就足够了。
data
,并将其应用到批处理文件中。例如,如果您希望PowerShell命令设置环境变量,则使其输出<name>=<value>
字符串对,批处理文件可用于设置这些变量。for /f
解析为批处理文件的示例;请注意,引用可能会比较棘手:@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]