Connect to Microsoft Exchange PowerShell within C# Connect to Microsoft Exchange PowerShell within C# powershell powershell

Connect to Microsoft Exchange PowerShell within C#


Check https://blogs.msdn.microsoft.com/akashb/2010/03/25/how-to-migrating-exchange-2007-powershell-managed-code-to-work-with-exchange-2010/:

The management experience given by Exchange 2010 through PowerShellhas been moved all the way from Local to Remote. [...] Only exchange cmdlets will work in this remoting scenario, you will not be able to run most of the powershell cmdlets. [...] Yes, this does mean that you will not be able to run cmdlets like Where-Object and .PS1 scripts in the Remote Runspace.

Is that a limitation? I don’t think so. We can very easily get around it by create a new Session and Importing it.


So you'll need to do something like this:

PSCredential creds = new PSCredential(userName, securePassword);System.Uri uri = new Uri("http://Exchange-Server/powershell?serializationLevel=Full");Runspace runspace = 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");powershell.Commands = command;runspace.Open(); powershell.Runspace = runspace;Collection<PSSession> result = powershell.Invoke<PSSession>();powershell = PowerShell.Create();command = new PSCommand();command.AddCommand("Set-Variable");command.AddParameter("Name", "ra");command.AddParameter("Value", result[0]);powershell.Commands = command;powershell.Runspace = runspace;powershell.Invoke();powershell = PowerShell.Create();command = new PSCommand();command.AddScript("Import-PSSession -Session $ra");powershell.Commands = command;powershell.Runspace = runspace;powershell.Invoke();# now you can use remote PS like it's local one


Starting from Exchange Server 2010 you need to use remote PowerShell session instead of adding exchange PowerShell snapin directly (due to using RBAC instead of ACL in exchange 2010). So you need to create new PowerShell session (using New-PSSession) and then import it (using Import-PSSession).You can use code like this to execute you PowerShell commands remote:

void ExecutePowerShellUsingRemotimg(){    RunspaceConfiguration runspaceConfig = RunspaceConfiguration.Create();    PSSnapInException snapInException = null;    Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfig);    runspace.Open();    Pipeline pipeline = runspace.CreatePipeline();    string serverFqdn = "FQDN of you server";    pipeline.Commands.AddScript(string.Format("$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://{0}/PowerShell/ -Authentication Kerberos", serverFqdn));    pipeline.Commands.AddScript("Import-PSSession $Session");    pipeline.Commands.AddScript("your PowerShell script text");    pipeline.Commands.Add("Out-String");    Collection<PSObject> results = pipeline.Invoke();    runspace.Close();    StringBuilder sb = new StringBuilder();    if (pipeline.Error != null && pipeline.Error.Count > 0)    {        // Read errors        succeeded = false;        Collection<object> errors = pipeline.Error.ReadToEnd();        foreach (object error in errors)            sb.Append(error.ToString());    }    else    {        // Read output        foreach (PSObject obj in results)            sb.Append(obj.ToString());    }    runspace.Dispose();    pipeline.Dispose();}


It looks like your running into double hop authentication problems, I've had the very same issues when trying to this.

After messing around I ended up installing the Exchange Powershell addins locally and used them to connect remotely to the Exchange server.

Rough example:

    RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create();    PSSnapInInfo info = runspaceConfiguration.AddPSSnapIn("Microsoft.Exchange.Management.PowerShell.Admin", out snapInException);                                        Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration);    runspace.Open();    using (PowerShell powershell = PowerShell.Create())    {        powershell.Runspace = runspace;        string script = string.Format(@"Get-Mailbox -Server {0} -Identity {1}", serverName, identity);        powershell.AddScript(script);        powershell.Invoke();       // Do something with the output    }