Using multiple Powershell sessions in C# application

by MarioVerhaeg at 2012-11-22 06:58:59

I’m searching for a problem for a couple of weeks now, and I can’t find the answer. I want to build an application that maintains powershell connections to 64 systems. For each system there needs to be a separate runspace (in manual terms: each system needs to have it’s own window) where I can execute commands. The idea is to create a global queue, where I push commands to. The application works out which command needs to be executed on which (or multiple) system(s). This way we can execute commands on multiple systems in parallel with a mouse click (there will be a front-end with build-in tasks).

Basically: I want to create an application with manages Powershell connections in an efficient way. Is this possible, and how?
by DonJ at 2012-11-23 12:21:27
You’re talking Remoting connections? I’m not sure why the need for separate windows. When you start a New-PSSession to a remote machine, PowerShell is running on that machine - so it’s a unique runspace on that machine. You’d simply create the New-PSSession objects, and then use Invoke-Command and its -Session parameter to target whichever open sessions you wanted.

I mean… maybe I’m not understanding what you’re saying, but this sounds like what Remoting already does?
by DougFinke at 2012-11-23 12:45:18
I was going to follow the line Don is. You can create multiple RunSpaces in a C# application.

Can you talk a bit more about what and how you’d like to accomplish?

Also, I show how to work with a PS Runspace in this chapter from my book, here is the source.

Thanks
Doug
by MarioVerhaeg at 2012-11-24 02:11:04
We are using 64 ESXi hosts at this moment, and are already using PowerCLI to talk to them via vCenter. This communication is very slow for the commands we are using, so my idea was to create a PowerCLI proxy application. This application is having a live connection to the 64 hosts and vcenter (because initiating the connection already takes a couple of seconds). A client application is talking to the proxy and sending commands to it, the proxy then sends the command to the correct host (or vcenter) and send the results back to the client application.

My initial idea was the create a thread for each hosts with a thread ID. If a command comes in, the proxy application looks up the host and thread, and sends the command to the thread (via some sort of queuing system, i haven’t thought this part true, i first want to setup the initial connection). This way, if a command takes long to execute (this can take up to a couple of minutes), it runs in a seperate thread an the proxy application can serve commands for other hosts in the meantime. Returning the results will also working with somekind of a queuing system (the thread pushing the result on the queue and the main thread sends the result back to the client application).
It looks like the runspace / pipeline objects in C# aren’t threadsafe, so I’m looking for other ways to accomplish this.

I’m using a local normal Powershell session runspace, and then I load the VMware PowerCLI into this runspace manually. After this i connect to the PowerCLI host via connect-viserver. Maybe this runspace isn’t really running remote, but local?
by craigmartin at 2012-11-25 20:58:19
I was thinking of doing something similar for a DLL that I have that calls PowerShell scripts. My goal would be to improve performance by creating a bunch of runspaces ahead of time, and just connecting to them as my DLL needs to run scripts.

Haven’t tried it yet, or learned enough about it to even start.
by MarioVerhaeg at 2012-11-27 03:01:06
TR1 2012-11-27 16:13:53 Executing command: Get-Date
TR2 2012-11-27 16:13:53 Executing command: Get-Date
TR1 2012-11-27 16:13:53 Result: 27-11-2012 16:13:53
TR1 2012-11-27 16:13:53 Executing command: Add-PSSnapin VMware.VimAutomation.Core
TR2 2012-11-27 16:13:53 Result: 27-11-2012 16:13:53
TR2 2012-11-27 16:13:53 Executing command: Add-PSSnapin VMware.VimAutomation.Core
TR1 2012-11-27 16:13:54 Executing command: Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
TR1 2012-11-27 16:13:54 Executing command: Connect-VIServer -Verbose -Server vensup014.x.nl -Protocol https -User xx -Password xx
TR2 2012-11-27 16:13:55 Executing command: Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
TR2 2012-11-27 16:13:55 Executing command: Connect-VIServer -Verbose -Server vensup004.x.nl -Protocol https -User xx -Password xx
TR2 2012-11-27 16:14:03 Result: vensup004.x.nl

I’m using two threads (TR1 and TR2). The thread handling the last request returns a result and is connected to the host (I’ve confirmed this with a wireshark trace).

Any ideas?
by MarioVerhaeg at 2012-12-05 03:24:49
It took me a lot of time, but finally got this part to work:

PowerShellProcessInstance pspi = new PowerShellProcessInstance();
pspi.Process.Start();
rs = RunspaceFactory.CreateOutOfProcessRunspace(TypeTable.LoadDefaultTypeFiles(), pspi);
Logging.Log.WriteTrace("Opening runspace");
rs.Open();


I’ve got no clue what is happening now (this was a lucky shot), and there is only a small amount of information available on these objects. I’m going to do some more research, but if someone else knows more about these objects I would appreciate all relevant information.