0

I receive the following error after running my WPF application for the fourth consecutive time:

Fail to create a runspace because you have exceeded the maximum number of connections allowed : 3 for the policy party : MaxConcurrency. Please close existing runspace and try again.

This error does not occur when opening the Runspace and PowerShell objects through a using (Runspace rs = RunspaceFactory.CreateInstance())... statement, as the resources seem to be properly disposed.

However, the way that this app is structured I would like to keep the Runspace/PowerShell object open between transactions because it takes a long time to create a remote session with Office 365 and I cannot keep users waiting to re-establish a remote session between every transaction.

When I keep these objects alive I then have to dispose of them manually as they are not contained within a using statement. I am using the following code:

namespace O365Wrapper
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : Application
    {
        public App()
        {
            InitializeComponent();
        }

        [STAThread]
        public static void Main()
        {
            App app = new App();
            cOofSettingsView view = new cOofSettingsView();
            app.Run(view);

            Thread.GetDomain().UnhandledException += new UnhandledExceptionEventHandler(OnUnhandledException);
            AppDomain.CurrentDomain.ProcessExit += new EventHandler(OnProcessExit);
        }

        public static void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            var ex = (Exception) e.ExceptionObject;
            MessageBox.Show(ex.Message);
            Environment.Exit(System.Runtime.InteropServices.Marshal.GetHRForException(ex));
        }

        public static void OnProcessExit(object sender, EventArgs e)
        {
            cPSConnection.DisposePowerShellEnvironment();
        }
    }
}

And in cPSConnection:

private static void InitializePowerShellEnvironment()
{
    if (_psrunspace == null || _psshell == null)
    {
        _psrunspace = RunspaceFactory.CreateRunspace();
        _psrunspace.Open();
        _psshell = PowerShell.Create();
        _psshell.Runspace = _psrunspace;
        CreatePowerShellSession();
    }
}

public static void DisposePowerShellEnvironment()
{
    if (_psshell != null)
    {
        _psshell.Dispose();
    }
    if (_psrunspace != null)
    {
        _psrunspace.Dispose();
    }
    _psshell = null;
    _psrunspace = null;
}

According to msdn the Runspace.Dispose method calls Runspace.Close if it has not been closed already.

One last item to note: _psshell and _psrunspace are only instantiated one time there are no incidental duplicate items created that might be lingering - the cPSConnection class is using the Singleton pattern.

The code that I currently have in place is an accumulation of borrowed code from already researching this problem, and I am still having no luck. Not sure where else to look. Any help would be much appreciated. Thanks!

Rhurac
  • 439
  • 4
  • 16
  • `using (Runspace rs = RunspaceFactory.CreateInstance())` will dispose `rs` for you. Where and how are you creating the `Runspace` in your current implementation? – mm8 Sep 28 '18 at 11:30
  • @mm8 Agreed, the `using` statement disposes `rs` correctly which leads me to believe I should be able to do so myself, without a `using` statement. This is what I am trying to accomplish. The `Runspace` and `Powershell` objects will be used in different places at different times and thus must be available in a scope larger than a `using` block, unless I re-initialize them with a `using` block each time. I do not wish to do this because it takes a lot of time to establish a remote session each time I initialize these objects. – Rhurac Sep 28 '18 at 20:17
  • @mm8 `Runspace` and `PowerShell` objects are both created in `cPSConnection` in the usual fashion, minus the `using` block. `cPSConnection` is a Singleton class with members `_psrunspace` and `_psshell`. These members are lazily loaded and kept alive for reuse, rather than disposed of immediately within a `using` statement. Any ideas on why the code I have posted is not disposing of these objects correctly? Thanks! – Rhurac Sep 28 '18 at 20:24
  • @mm8 I added the initialization code for `Runspace` and `PowerShell` objects for you to see. The call to `CreatePowerShellSession` then goes on to connect to O365 services, similar to the method described at: https://learn.microsoft.com/en-us/office365/enterprise/powershell/connect-to-all-office-365-services-in-a-single-windows-powershell-window – Rhurac Sep 28 '18 at 20:34

0 Answers0