如何通过System.Management在独立PowerShell Shell中创建Runspace
问题分析与解决方案
首先纠正你的一个小误解:你对独立PowerShell窗口中Runspace的理解是正确的——每个PowerShell窗口都是独立的进程,它们的Runspace1属于各自的进程,互相不可见,只是名字相同而已。
而你的代码中出现的问题,根源在于默认的Runspace池机制:
当你调用PowerShell.Create()时,.NET会默认使用进程级的Runspace池来管理Runspace实例。第一次调用时,池会创建Runspace1并复用它;第二次调用时,如果池里的Runspace处于忙碌状态,就会创建新的Runspace2加入池。此时执行Get-Runspace会列出当前进程内所有的Runspace(包括池中的所有实例),所以第二次输出会同时看到两个Runspace。
实现独立Runspace的方案
要让每个PowerShell会话使用完全独立、互相不可见的Runspace,你需要手动创建并绑定独立的Runspace实例,而不是依赖默认的池。具体代码如下:
using System; using System.Management.Automation; using System.Management.Automation.Runspaces; class Program { static void Main(string[] args) { for (int i = 1; i <= 2; i++) { // 创建一个全新的独立Runspace,不加入共享池 using (var runspace = RunspaceFactory.CreateRunspace()) { runspace.Open(); // 将PowerShell实例绑定到这个独立Runspace using (PowerShell ps = PowerShell.Create()) { ps.Runspace = runspace; ps.AddCommand("Get-Runspace"); var result = ps.Invoke(); foreach (PSObject elem in result) { Runspace rs = (Runspace)elem.BaseObject; Console.WriteLine(rs.Name); } Console.WriteLine(); } runspace.Close(); } } Console.ReadLine(); } }
为什么这个方案有效?
- 手动创建的
Runspace实例属于独立会话,不会被加入进程级共享池。 - 每个PowerShell实例都绑定到专属的Runspace,执行
Get-Runspace时只会返回当前Runspace本身,不会看到其他会话的Runspace。 - 使用
using语句确保Runspace在使用后被正确销毁,不会残留进程中。
补充说明
你提到“关闭Runspace无法解决问题”,这是因为默认池中的Runspace关闭后会被放回池(处于闲置状态),而不是真正销毁,所以后续调用仍能看到它。而手动创建的Runspace在using块结束后会被彻底释放,不会留在进程中。
内容的提问来源于stack exchange,提问作者Norberth Csorba
相关产品推荐
相关产品推荐

