Access Exchange Online by PowerShell in C#

For exchange online management, the most convenient and powerful approach is Exchange Online PowerShell Cmdlet. Before calling each management cmdlet, we need establish a remote session firstly and Connect to Exchange Online PowerShell is a good start for this.


In the meantime, probably you would like to access exchange online from C#, such as a desktop application to provide management flexibility. This blog is regarding to this scenario step by step.


Step 1

Firstly, we need construct a PSCredential object for user and secured password. connectionUril is same to all the office 365 tenant, and will be used later to establish the remote session.

string connectionUri = "";
string loginPassword = "thepassword";
SecureString secpassword = new SecureString();
foreach (char c in loginPassword)
PSCredential credential = new PSCredential("", secpassword);


Step 2

Create and open the runspace which is the container of the powershell session. the remote session will be established by cmdlet New-PSSession. We need check the error and result to make sure everything is going fine.

Runspace runspace = System.Management.Automation.Runspaces.RunspaceFactory.CreateRunspace();
PowerShell powershell = PowerShell.Create();
PSCommand command = new PSCommand();
command.AddParameter("ConfigurationName", "Microsoft.Exchange");
command.AddParameter("ConnectionUri", new Uri(connectionUri));
command.AddParameter("Credential", credential);
command.AddParameter("Authentication", "Basic");
powershell.Commands = command;

powershell.Runspace = runspace;
Collection<System.Management.Automation.PSObject> result = powershell.Invoke();
if (powershell.Streams.Error.Count > 0 || result.Count != 1)
throw new Exception("Fail to establish the connection");


Step 3

Let’s try to retrieve all the mailboxes by cmdlet Get-Mailbox. As we need run the command in the remote session just established, we need Invoke-Command as it provides the ability to run the command in a specific session. In this example, we will get all the mailbox and select the target based on DisplayName.

powershell = PowerShell.Create();
command = new PSCommand();
command.AddParameter("ScriptBlock", System.Management.Automation.ScriptBlock.Create("Get-Mailbox"));
command.AddParameter("Session", result[0]);
powershell.Commands = command;
powershell.Runspace = runspace;
var mailBoxes = powershell.Invoke();
var targetBox = mailBoxes.Where(i => (string)i.Properties["DisplayName"].Value == "Jacky Wu").FirstOrDefault();
var identity = targetBox.Properties["Identity"].Value;


Step 4

Based on the identity retrieved in last step, let’s call Set-Mailbox to set the corresponding IssueWarningQuota.

powershell = PowerShell.Create();
command = new PSCommand();
command.AddParameter("ScriptBlock", System.Management.Automation.ScriptBlock.Create("Set-Mailbox -Identity " + identity + " -IssueWarningQuota 16GB"));
command.AddParameter("Session", result[0]);
powershell.Commands = command;
powershell.Runspace = runspace;


Step 5

Lastly, we need dispose the runspace to release the connection. By default, the maximum number of the concurrent remote connections is 3. Certainly, it is a good idea to wrap the above code in a try-finally block to make it. By the way, notice that I just execute Get-MailBox and Set-MailBox in two separate invokes to demonstrate get and set usage, feel free to compose more complicated command combination such as pipeline in a single invoke-command.


Basically, access exchange online cmdlet from C# is not as straightforward as Powershell script directly, may be more suitable for lightweight management. The above code is confirmed to work in exchange on-premises as well, while need some code revise such as connectionUri and Authentication (set to default). Hope this is helpful.


Comments (3)

  1. Thanks for clarifying this complex issue in simple English.

  2. No tengo comentarios. gracias…

  3. Jian-Wei Yu says:

    Great blog, and really helpful!!!

Skip to main content