PowerShell中如何使用回调函数执行异步WMI查询
PowerShell 实现基于SWbemSink的WMI异步查询方法
差异说明
VBScript创建WbemScripting.SWbemSink时支持传入回调前缀参数,运行时会自动匹配当前作用域下对应前缀开头的子过程作为事件回调,属于VBScript独有的隐式事件绑定逻辑。
PowerShell对COM对象的默认封装不会直接暴露事件成员,通过New-Object创建的sink对象默认仅显示公开的Cancel()方法,事件需要通过PowerShell原生的事件注册机制手动绑定,无隐式匹配规则。
具体实现代码
# 初始化COM对象 $sink = New-Object -ComObject WbemScripting.SWbemSink $wmiService = GetObject("winmgmts://./root/cimv2") # 绑定单对象返回事件:每匹配到一条WMI记录触发一次 Register-ObjectEvent -InputObject $sink -EventName OnObjectReady -Action { $wmiInstance = $EventArgs.NewEvent.Item(0) # 自定义处理逻辑,示例为输出进程名和PID Write-Host "进程名:$($wmiInstance.Name),进程ID:$($wmiInstance.ProcessId)" } | Out-Null # 绑定查询完成事件:整个异步查询执行结束后触发 Register-ObjectEvent -InputObject $sink -EventName OnCompleted -Action { $errorCode = $EventArgs.NewEvent.Item(0) Write-Host "`n异步查询执行完成,返回状态码:$errorCode" } | Out-Null # 发起异步WMI查询 $wmiService.ExecQueryAsync($sink, "SELECT * FROM Win32_Process") # 保持脚本运行等待事件触发,可根据业务场景替换为其他逻辑 while ($true) { Start-Sleep -Milliseconds 500 }
关键说明
- 事件回调的参数统一存在
$EventArgs.NewEvent集合中,按触发事件的参数顺序索引取值:OnObjectReady事件索引0为查询到的WMI实例,索引1为调用时传入的上下文对象;OnCompleted事件索引0为查询状态码,索引1为上下文对象 - 可通过
ExecQueryAsync的第四个参数传入自定义上下文对象,在回调中读取实现参数传递 - 提前终止查询时直接调用
$sink.Cancel()即可,脚本退出前可执行Get-EventSubscriber | Unregister-Event清理事件订阅,避免残留订阅占用资源 - 不需要像VBScript一样固定回调函数命名,所有回调逻辑直接写在
Register-ObjectEvent的-Action脚本块内即可
内容的提问来源于stack exchange,提问作者Charles
相关产品推荐
相关产品推荐

