Home » Microsoft TechnologiesRSS

How do I re-establish a failed remote powershell connection or avoid leaking memory in C#

We are using C# code similar to following to establish a remote powershell session to manage an Exchange 2010 server:

 

MyCode {

            System.Security.SecureString securePassword = new System.Security.SecureString();

            foreach (char c in password.ToCharArray())

            {

                securePassword.AppendChar(c);

            }

 

            PSCredential creds = new PSCredential(userName, securePassword);

            _r = RunspaceFactory.CreateRunspace();

 

            PowerShell powershell = PowerShell.Create();

            PSCommand command = new PSCommand();

            command.AddCommand("New-PSSession");

            command.AddParameter("ConfigurationName", "Microsoft.Exchange");

            command.AddParameter("ConnectionUri", uri);

            command.AddParameter("Credential", creds);

            command.AddParameter("Authentication", "Default");

 

            PSSessionOption sessionOption = new PSSessionOption();

            sessionOption.SkipCACheck = true;

            sessionOption.SkipCNCheck = true;

            sessionOption.SkipRevocationCheck = true;

            command.AddParameter("SessionOption", sessionOption);

            powershell.Commands = command;

 

            _r.Open();

            powershell.Runspace = _r;

 

            Collection<PSSession> result = powershell.Invoke<PSSession>();

            foreach (ErrorRecord current in powershell.Streams.Error)

            {

               // log errors

            }

 

            if (result.Count != 1)

                throw new Exception("Unexpected number of Remote Runspace connections returned.");

 

            powershell = PowerShell.Create();

            command = new PSCommand();

            command.AddCommand("Set-Variable");

            command.AddParameter("Name", "ra");

            command.AddParameter("Value", result[0]);

            powershell.Commands = command;

            powershell.Runspace = _r;

            powershell.Invoke();

 

            powershell = PowerShell.Create();

            command = new PSCommand();

            command.AddScript("Import-PSSession -Session $ra");

            powershell.Commands = command;

            powershell.Runspace = _r;

            powershell.Invoke();

 

            // Wait for incoming commands, invoke as they arrive

}

 

This approach works fine, unless, as in a particular environment, the heartbeat mechanism between the remote powershell and the server (every 3-4 minutes, as we understand it) fails for whatever reason.  In this case, an exception is thrown trying to execute a subsequent provisioning command:  << Exception calling "PromptForCredential" with "4" argument(s): "Cannot invoke this function because the current host does not implement it." >>

 

When this happens, we simply establish a new powershell session using the code above, and all is well, except that each time this occurs, the process eats up an additional 25-50 MB of memory.  We’ve tried calling combinations of powershell.Dispose(), powershell = null, _r.Dispose(), _r = null, System.GC.Collect() and “Remove-PSSession” to no avail.

 

Our question, then, is twofold:  a) Is there some other way to free up the memory used by the original connection, and/or b) Is there some way to “awaken” the original powershell session when the heartbeat has failed, to avoid having to create a new session?

 

Thanks in advance for any ideas.


<< Previous      Next >>


Microsoft   |   Windows   |   Visual Studio   |   Follow us on Twitter