1

I am developing a server side Blazor app to facilitate Exchange online management via a GUI. I have a helper class that setups the runspace and communicates the results back to the the Blazor component. I added the class via an scoped Dependency Injection.

The helper class is setup as:

    InitialSessionState runspaceConfiguration = InitialSessionState.CreateDefault();
    runspaceConfiguration.ExecutionPolicy = Microsoft.PowerShell.ExecutionPolicy.RemoteSigned;
    runspaceConfiguration.ImportPSModule("ExchangeOnlineManagement");
    runspaceConfiguration.ThrowOnRunspaceOpenError = true;
    _runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration);
    // Open local runspace
    _runspace.Open();
    _shell = PowerShell.Create();
    _shell.Runspace = _runspace;
    SetUpEventHandlers();

My function to execute commands is a follow:

public async Task ExecuteScript(string scriptContents)
{
    _shell.AddScript(scriptContents);
    OutputEventArgs rtc = new() {
       Data = await _shell.InvokeAsync().ConfigureAwait(true)
    };
    _shell.Streams.ClearStreams();
    _shell.Commands.Clear();
    ResultsAvailable?.Invoke(this, rtc);
}

To connect to Exchnage Online I use a certificate, it looks like:

    string? certificateThumbPrint = config.GetValue<string>("certificateThumbPrint");
    string? appId = config.GetValue<string>("appId");
    string? tenant = config.GetValue<string>("tenant");
    logger.Info($"Running : Connect-ExchangeOnline -Certificate {certificateThumbPrint} -AppID {appId} -Organization {tenant} -ShowProgress $false -ShowBanner $false");
    string scriptContents = $"Connect-ExchangeOnline -CertificateThumbPrint {certificateThumbPrint} -AppID {appId} -Organization {tenant}";
    await objPowerShell.ExecuteScript(scriptContents);

I have setup EventHandler's that handle all the streams and results async, and everything works fine for one user. The problem is when I have multiple users. It still all works fine, except when one user disconnects the session, all active connections to the Exchange Online environment are disconnected. As I am using EXO v3, I cannot save the PSSession and import it.

So my question is how can I disconnect one user without having an impact on the other.

I did tried to do the same thing directly in PowerShell:

    $Initialstate = [InitialSessionState]::CreateDefault()
    $RunspacePool = [runspacefactory]::CreateRunspacePool(1,5)
    $RunspacePool.Open()
    $Runspace1 = [runspacefactory]::CreateRunspace()
    $PowerShell1 = [powershell]::Create()
    $PowerShell1.RunspacePool = $RunspacePool
    $Runspace1.Open()
    [void]$PowerShell1.AddScript({
        $cert = Get-ChildItem Cert:\LocalMachine\My\0CF..4C17.
        Connect-ExchangeOnline -Certificate $cert -AppID 70539...5889 -Organization myorg.onmicrosoft.com
    })
    $PowerShell1.Invoke()
    $PowerShell1.Commands.Clear()
    [void]$PowerShell1.AddScript({
        Get-ConnectionInformation
    })
    $conn1 = $PowerShell1.Invoke()
    $PowerShell1.Commands.Clear()
    [void]$PowerShell1.AddScript({
        Get-MailBox "ue*" -resultsize 2 | Select-Object PrimarySmtpAddress
    })
    $mbx1 = $PowerShell1.Invoke()
    $mbx1 # Gets the info ok
    $PowerShell2 = [powershell]::Create()
    $PowerShell2.RunspacePool = $RunspacePool
    [void]$PowerShell2.AddScript({
        $cert = Get-ChildItem Cert:\LocalMachine\My\0CF.4C17D
        Connect-ExchangeOnline -Certificate $cert -AppID 70539...5889 -Organization myorg.onmicrosoft.com
    })
    $PowerShell2.Invoke()
    $PowerShell2.Commands.Clear()
    [void]$PowerShell2.AddScript({
        Get-ConnectionInformation
    })
    $conn2 = $PowerShell2.Invoke()
    $PowerShell2.Commands.Clear()
    [void]$PowerShell2.AddScript({
        Get-MailBox "uz*" -resultsize 2 | Select-Object PrimarySmtpAddress
    })
    $mbx2 = $PowerShell2.Invoke()
    $mbx2 # Gets the info ok

But when I execute now "Get-ConnectionInformation" I see 2 connections and "Disconnect-ExchangeOnline" disconnects them both. So, how can I only disconnect one ?

NicCarlos
  • 11
  • 1
  • You could use the rest api directly: https://www.michev.info/Blog/Post/3883/exchange-online-powershell-module-gets-rid-of-the-winrm-dependence . Or launch entirely separate powershell processes instead of runspaces. Otherwise, you can still use pssessions in V3 with `Connect-ExchangeOnline -UseRPSSession`. The EXOv3 module itself just clears all active connections/tokens like you've found - Maybe multiple sessions in a future release? – Cpt.Whale Dec 16 '22 at 22:02
  • Thanks Cpt. Whale for confirming my findings and for the link. I already tried it out in postman, and that seems to work fine. I 'll try it this way as I do not want to use 'UseRPSSession' as I get a warning info from Microsoft when I use them asking me why I am still using RPS cmdlets. Probably the 'UseRPSSession' is not a future proof way ? – NicCarlos Dec 19 '22 at 07:17
  • MS hasn't announced dropping support for exchange PS sessions yet, but yeah they are slower and may not get newer features as development shifts over to rest stuff – Cpt.Whale Dec 19 '22 at 16:38

0 Answers0