The management experience given by Exchange 2010 through PowerShell has been moved all the way from Local to Remote. This will mean that enterprise Admins will have to adjust their regular scripts to connect to Remote PowerShell instead of creating a local session.
Here are some examples on how can this be achieved and the differences that may have to be done in order to create the connection and run the cmdlets.
Using programmatic API
The programmatic API is the simplest method that will allow you to make a remote connection requiring only the Uri for the connection and a set of suitable credentials that need to be provided through a method.
SCredential credential = new PSCredential(username, password);
Note: The password here must be of type SecureString.
After you just need to create the connection Information that will allow the creation of the runspace.
// Set the connection Info
WSManConnectionInfo connectionInfo = new WSManConnectionInfo(
new Uri(liveIdconnectionUri),
http://schemas.microsoft.com/powershell/Microsoft.Exchange,
credential);
connectionInfo.AuthenticationMechanism = AuthenticationMechanism.Basic;
// create a runspace on a remote path
// the returned instance must be of type RemoteRunspace
Runspace runspace = System.Management.Automation.Runspaces.RunspaceFactory.CreateRunspace(connectionInfo);
From here it is just you only need to create a PowerShell instance and fill it with your cmdlets and then invoke it through the run space we've just created. Here is a simple example with get-mailbox.
PowerShell powershell = PowerShell.Create();
PSCommand command = new PSCommand();
command.AddCommand("Get-Mailbox");
command.AddParameter("Identity", mailboxName);
powershell.Commands = command;
try
{
// open the remote runspace
runspace.Open();
// associate the runspace with powershell
powershell.Runspace = runspace;
// invoke the powershell to obtain the results
return powershell.Invoke();
}
finally
{
// dispose the runspace and enable garbage collection
runspace.Dispose();
runspace = null;
// Finally dispose the powershell and set all variables to null to free
// up any resources.
powershell.Dispose();
powershell = null;
}
Using Programmatic API and Certificate Thumbprint
This uses the exact same syntax than the Programmatic API except that we would need to connect to a Uri that is has a Certificate Thumbprint enabled when we create the WSMAN connection in this syntax.
WSManConnectionInfo connectionInfo = new WSManConnectionInfo(
"E75C847ADF7B355DAAC2C6D1A4EDD8284A0C0FDC",
new Uri(certconnectionUri),
"http://schemas.microsoft.com/powershell/Microsoft.Exchange");
Remote Request using a local run space (Scripting the remote class)
This is the best to create scripts and run your cmdlets using remote PowerShell. For this case, we have to script in the code a call to create a New-PSSession using our credential, the connection Uri and method of authentication. This is basically using the cmdlet:
New-PSSession -ConnectionUri Microsoft.Exchange -ConnectionUri $Uri -Credential $LiveCred -Authentication Basic
To do this, we have to create the Run space in which we will run the cmdlet and then create a PowerShell instance to add the cmdlet.
Runspace runspace = System.Management.Automation.Runspaces.RunspaceFactory.CreateRunspace();
PowerShell powershell = PowerShell.Create();
PSCommand command = new PSCommand();
command.AddCommand("New-PSSession");
command.AddParameter("ConfigurationName", "Microsoft.Exchange");
command.AddParameter("ConnectionUri", new Uri(liveIdconnectionUri));
command.AddParameter("Credential", cred);
command.AddParameter("Authentication", "Basic");
powershell.Commands = command;
Now invoke this cmdlet and set it as a variable on the local Run Space that will be used to do the remote calls.
try
{
// open the remote runspace
runspace.Open();
// associate the runspace with powershell
powershell.Runspace = runspace;
// invoke the powershell to obtain the results
Collection<RemoteRunspaceInfo> result = powershell.Invoke<RemoteRunspaceInfo>();
foreach (ErrorRecord current in powershell.Streams.Error)
Console.WriteLine("The following Error happen when opening the remote Runspace: " + current.Exception.ToString() + " | InnerException: " + current.Exception.InnerException);
if (result.Count != 1)
throw new Exception("Unexpected number of Remote Runspace connections returned.");
// Set the runspace as a local variable on the runspace
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();
After we have done this, we can now do the remote calls that will be executed on the server side as script blocks.
powershell = PowerShell.Create();
command = new PSCommand();
command.AddScript("Invoke-Command -ScriptBlock { Get-Mailbox -Identity:" + mailboxName + " } - Session $ra");
powershell.Commands = command;
powershell.Runspace = runspace;
return powershell.Invoke();
}
finally
{
// dispose the runspace and enable garbage collection
runspace.Dispose();
runspace = null;
// Finally dispose the powershell and set all variables to null to free
// up any resources.
powershell.Dispose();
powershell = null;
}
Hi, I am in the process of creating a project around remoting via Powershell from 2008 C#/VB using powershell 2.0 & WinRM 2.0 from a Windows Server 2008 SP2 machine. I have added the system.management.automation reference, but I am unable expose the RemoteRunspaceInfo class and my code therefore fails. I cannot seem to expose in the fashion listed in the example above. Can you provide more information around which this class.
The sticking point for me seems to be the liveIdConnectionUri… what should be there? I’m using an Exchange 2010 installation that is not federated… should I point to
https://login.live.com?
when executed a powershell 2.0 command using vb.net to add mailbox to MS Exchange 2010 having WinRM client and server machines as same machine, i encountered the following error.
"The WinRM client cannot process the request. The authentication mechanism requested by the client is not supported by the server or unencrypted traffic is disabled in the service configuration. Verify the unencrypted traffic setting in the service configuration or specify one of the authentication mechanisms supported by the server. To use Kerberos, specify the computer name as the remote destination. Also verify that the client computer and the destination computer are joined to a domain. To use Basic, specify the computer name as the remote destination, specify Basic authentication and provide user name and password. Possible authentication mechanisms reported by server: For more information, see the about_Remote_Troubleshooting Help topic."
Environment i am using is
Windows Server 2008 R2 64-bit
MS Exchange 2010
PowerShell V2.0
Hi ,
i executed following code to get MailBoxDatabase
Dim Pass As New System.Security.SecureString
Dim MyPassword As String = Password
For Each c As Char In MyPassword
Pass.AppendChar(c)
Next
Dim credential As PSCredential = New PSCredential(UserName, Pass)
Dim connectionInfo As New WSManConnectionInfo(New Uri("http://" & FQDN & "/powershell?serializationLevel=Full"), "http://schemas.microsoft.com/powershell/Microsoft.Exchange", credential)
connectionInfo.AuthenticationMechanism = AuthenticationMechanism.Kerberos
Dim RSpace As Runspace
Try
RSpace = System.Management.Automation.Runspaces.RunspaceFactory.CreateRunspace(connectionInfo)
Catch ex As Exception
Throw New Exception("RSPACE: " & ex.Message)
End Try
Dim Shell As PowerShell = PowerShell.Create()
Dim PCommand As New PSCommand
Try
PCommand.AddCommand("Get-MailboxDatabase")
PCommand.AddParameter("Server", New Microsoft.Exchange.Configuration.Tasks.ServerIdParameter(New Microsoft.Exchange.Data.Fqdn(ServerName)))
‘ PCommand.AddParameter("DomainController", PreferredDC)
Shell.Commands = PCommand
Catch ex As Exception
Throw New Exception("Build command: " & ex.Message)
End Try
Dim results As Collection(Of PSObject)
Dim Msg As String
Dim Databases As String
Try
RSpace.Open()
Shell.Runspace = RSpace
results = Shell.Invoke()
Dim Enm As System.Collections.Generic.IEnumerator(Of System.Management.Automation.PSObject) = results.GetEnumerator
Dim index As Integer = 0
Do While Enm.MoveNext()
Databases = Enm.Current.Members("Identity").Value.ToString ‘& "" & Enm.Current.Members("AdminDisplayName").Value.ToString
Loop
RSpace.Close()
Catch err As Exception
Throw New Exception("Run command: " & err.Message)
Finally
RSpace.Dispose()
RSpace = Nothing
Shell.Dispose()
Shell = Nothing
End Try
and encountered the following error.
Cannot process argument transformation on parameter ‘Server’. Cannot convert the "Clients.exmtemp.com" value of type "Deserialized.Microsoft.Exchange.Configuration.Tasks.ServerIdParameter" to type "Microsoft.Exchange.Configuration.Tasks.ServerIdParameter".
any help regarding above issue will be appreciated.
Thanks in Advance.
Best Regards,
cute devil
How can I write a code that recognize the exchange powershell and the basic powershell?
I mean:
get-mailbox | Format-list
Format-list is not recognized as a powershell command, when I use the constructor with the credential!!
What should the liveIdconnectionUri be in
WSManConnectionInfo connectionInfo = new WSManConnectionInfo(
new Uri(liveIdconnectionUri),
"http://schemas.microsoft.com/powershell/Microsoft.Exchange",
credential);
looks like liveIdConnectionUri should be
https://ps.outlook.com/powershell/
found it here:
http://help.outlook.com/en-us/140/cc713521.aspx#ScriptOptions