Search code examples
c#powershellexchange-server

Using Exchange Online PowerShell with C#


I have a bit of an issue with some code that's meant to load the Exchange Online PowerShell module behind the scenes to do things in an application on behalf of users who don't have access to Exchange Online themselves. However, I'm having problems getting the shell to load.

My code so far:

using (var rs = RunspaceFactory.CreateRunspace())
{
    rs.Open();
    using (var ps = PowerShell.Create())
    {
        ps.Runspace = rs;
        var cred = new PSCredential(user, MakeSecureString(pwd)); // Credential for the GA user
        var setProxy = Encoding.UTF8.GetString(Convert.FromBase64String(Properties.Resources.PSProxy)); // Set network proxy options in the shell
        ps.AddScript(setProxy);
        ps.Invoke();
        ps.AddScript(Encoding.UTF8.GetString(Convert.FromBase64String(Properties.Resources.SetupExoModule))); // Install the Exchange Online Management module in the user context if not already present
        ps.Invoke();
        PSCommand importModule = new PSCommand();
        importModule.AddCommand("Import-Module");
        importModule.AddParameter("Name", "ExchangeOnlineManagement");
        ps.Commands = importModule;
        ps.Invoke(); // Fails here
        // Connect and perform actions as needed
    }
}

The module installs, if not already installed, but always fails to load. From testing I have found that if the applicable PowerShell ExecutionPolicy is set to anything other than "Undefined" I get the error:

Unable to find type [Microsoft.Exchange.Management.RestApiClient.ExchangeEnvironment].

If the policy is set to "Undefined" then I get an error saying that running scripts is disabled on the system.

Interestingly, if I open PowerShell itself and run the commands to connect, it works fine, so both PowerShell and the Exchange module would seem to be OK.

Has anyone else encountered a problem like this? Grateful for any advice on how I can get this working.


Solution

  • Thank you for all the pointers in the comments guys. It turns out that the issue was down to the fact that someone had enabled AppLocker on a set of workstations and this was blocking the Exchange Online shell from loading via code - the shell was happy enough to load when running in actual PowerShell though.

    I believe this is down to how the shell works. It seems that when it's run it gets copied from its install location in Program Files to a temporary location in %AppData% and as AppLocker was blocking scripts from temporary locations, the execution failed.