Using Credentials to Get Remote PowerShell Connection to Exchange Connection
Saw this come across the search logs so I figured I’d detail the steps needed to supply credentials to a remote PowerShell connection to Exchange. Since we’re connecting to another system to run the Exchange PS cmdlets, and we are not loading a PSSnapin, the remote system needs to have those cmdlets available. I’m also separating this out into individual methods for easy re-use.
To setup a remote connection, we need to create a new WSManConnectionInfo object. We’re specifically going to use the constructor that takes a Uri for the connection endpoint, a string value for the Uri of the shell and the credentials we want to use.
WSManConnectionInfo Constructor (Uri, String, PSCredential)
The Uri will be specific to your situation and will look something like this : http://myexchangeserver.domain.corp/powershellThe shell is pretty simple. In this case it is : http://scemas.microsoft.com/powershell/Microsoft.Exchange
And last but not least it the PSCredential needed for the connection. PSCredential takes a string for the Username and a SecureString for the password. Here’s an small method to pass in a string and get a SecureString back :
SecureString GetSecurePassword(string password) { var securePassword = new SecureString(); foreach (var c in password) { securePassword.AppendChar(c); } return securePassword; }
With that out of the way, let’s take a look at a snippet for getting the connection info :
WSManConnectionInfo GetConnectionInfo() { var securePassword = GetSecurePassword(password); var cred = new PSCredential(username, securePassword); var connectionInfo = new WSManConnectionInfo(new Uri("http://superserver.corp/powershell), "http://schemas.microsoft.com/powershell/Microsoft.Exchange", cred); connectionInfo.AuthenticationMechanism = AuthenticationMechanism.Credssp; //or Basic, Digest, Kerberos etc. return connectionInfo; }
Now let’s put it all together to make a remote connection :
using (var runspace = RunspaceFactory.CreateRunspace(connectionInfo)) { using (var ps = System.Management.Automation.PowerShell.Create()) { //psCommand was created above ps.Commands = psCommand; runspace.Open(); ps.Runspace = runspace; try { var results = ps.Invoke(); if (!ps.HadErrors) { runspace.Close(); //Yay! no errors. Do something else? } catch (RemoteException ex) { //error handling here } } }
So, a couple of things to mention here. First, psCommand was created like this. You could also create a Pipeline if you have more than one command to run or even use it to create a PS script to run. Also, if you need to do something with the results of the command, well, you’ll have to either make this return the results ((FavoriteCollectionType) or modify this to suit your needs. Second, we verify that the command had no errors (no exception but didn’t run successfully for whatever reason) but that’s it. Might want to expand here or in the calling method.
I hope this has been informative. 😀