I'm trying to run different PowerShell commands using .NET's System.Management library but I see that every time the runspaces share the same shell. To be more specific, if I open one PowerShell window on my OS and I run the following command:
Get-Runspace
I get the following output:
Id Name ComputerName Type State Availability
-- ---- ------------ ---- ----- ------------
1 Runspace1 localhost Local Opened Busy
If I now open another window and run the same command again I get the same output, from which I understand that I have different runspaces with the same name in different sessions. Correct me here if I'm wrong!
Now if I run the following code that runs the Get-Runspace
command twice:
static void Main(string[] args)
{
for (int i = 1; i <= 2; i++)
{
PowerShell ps = PowerShell.Create();
ps.AddCommand("Get-Runspace");
var result = ps.Invoke();
foreach (PSObject elem in result)
{
Runspace runspace = (Runspace)elem.BaseObject;
Console.WriteLine(runspace.Name);
}
Console.WriteLine();
}
Console.ReadLine();
}
I get the following output
Runspace1
Runspace1
Runspace2
which means that Runspace1 is visible from Runspace2 so they share the same shell.
I would instead expect the following output, in which the two runspaces are in separate shells:
Runspace1
Runspace1
Is this behaviour possible or my logic is broken? Note that closing the Runspace will not be enough to solve my problem.
If by "same shell" you mean "the same process", then yes.
A Runspace
is necessarily restricted to a single application domain, and application domains in .NET can't span multiple processes, so the relationship is:
+---------------------------------+
| Process |
| +-----------------------------+ |
| | AppDomain | |
| | +-----------+ +-----------+ | |
| | | Runspace1 | | Runspace2 | | |
| | +-----------+ +-----------+ | |
| +-----------------------------+ |
+---------------------------------+
Get-Runspace
just enumerates the runspaces in the current host application domain.
You can isolate runspaces in a separate process if need be, use RunspaceFactory.CreateOutOfProcessRunspace()
:
using (PowerShell ps = PowerShell.Create())
{
var isolatedShell = new PowerShellProcessInstance();
var isolatedRunspace = RunspaceFactory.CreateOutOfProcessRunspace(TypeTable.LoadDefaultTypeFiles(), isolatedShell);
ps.Runspace = isolatedRunspace;
ps.AddCommand("Get-Runspace");
var result = ps.Invoke();
foreach (PSObject elem in result)
{
Runspace runspace = (Runspace)elem.BaseObject;
Console.WriteLine(runspace.Name);
}
Console.WriteLine();
}