VB.NET运行PowerShell脚本后如何访问$online、$offline变量内容
问题本质
你当前无法读取$online、$offline的核心原因是:这两个变量是存储在PowerShell运行空间会话作用域中的自定义变量,全程没有被推送到PowerShell的输出管道中。而你通过InvokeAsync拿到的PSDataCollection(Of PSObject)仅收集管道内的输出对象,自然没法拿到这两个变量的内容。
两种可落地的实现方案
方案一:将目标变量主动推送至输出管道(最简单、无额外配置)
这种写法不需要改动原有变量的定义和判断逻辑,只需要在脚本末尾追加结构化输出代码,把两个变量的值推到管道里,后续在VB.NET中直接从返回结果读取即可:
- 在原有脚本的循环逻辑之后,追加一行输出代码:
' 原有循环的AppendLine代码写完之后,追加这行 scriptContents.AppendLine("return [PSCustomObject]@{ Online = $online; Offline = $offline }") - PowerShell执行完成后,从返回的结果集合中读取值:
这个方案的优势是不需要操作底层会话状态,兼容不同版本的System.Management.Automation,也不会受Runspace作用域配置的影响,是日常开发中最常用的实现方式。' 等待异步执行完全结束 Dim results1 As PSDataCollection(Of PSObject) = Await Task.Run(Function() ps.InvokeAsync) If results1.Count > 0 Then ' 取出刚才输出的自定义对象 Dim resultObj = results1.First() ' 读取两个属性的实际值,对应PowerShell里的两个字符串数组 Dim onlineComputers = resultObj.Properties("Online").Value Dim offlineComputers = resultObj.Properties("Offline").Value End If
方案二:通过会话状态代理直接读取变量(适合不能修改脚本输出逻辑的场景)
PowerShell实例执行完脚本后,脚本内定义的所有作用域变量都会临时保存在当前关联的Runspace中,你不需要修改原有脚本,直接通过SessionStateProxy接口就能读取对应变量的值:
- 保持现有脚本的所有内容完全不变,不需要追加任何输出代码
- 等到脚本全部执行完成后,直接读取会话中存储的变量:
' 必须等待异步执行全部完成,不能在执行过程中读取 Dim results1 As PSDataCollection(Of PSObject) = Await Task.Run(Function() ps.InvokeAsync) ' 通过会话状态代理直接获取定义的变量 Dim onlineComputers = ps.Runspace.SessionStateProxy.GetVariable("online") Dim offlineComputers = ps.Runspace.SessionStateProxy.GetVariable("offline")
开发注意事项
- 绝对不能在PowerShell脚本执行的过程中读取会话变量,此时变量还未完成赋值,读取会返回空值
- 如果使用Runspace对象池复用Runspace,需要做好变量的作用域隔离,避免不同脚本的自定义变量互相污染
- 你原有脚本中用数组
+=追加元素的写法,在计算机数量较少的测试场景下没有问题;如果需要检测上百台规模的主机,建议在PowerShell端使用泛型列表存储结果,减少频繁数组扩容带来的内存拷贝开销
内容的提问来源于stack exchange,提问作者Darren Rose
相关产品推荐
相关产品推荐

