views:

188

answers:

2

In Exchange 2007 this line of code is used to load the Exchange Poweshell commands snapin:

PSSnapInInfo info = rsConfig.AddPSSnapIn(
  "Microsoft.Exchange.Management.PowerShell.Admin",
  out snapInException);

However, this does not exist in Exchange 2010 and I am pulling my hair out trying to find out how to access the Exchange Powershell commands from C# code. Microsoft.Exchange.Management.PowerShell.Admin does not exist anywhere on the Exchange Server and I can find nothing on Google that talks about an equivalent line of code.

How do I access Exchange Management Tools from C# code in Exchange 2010?

Below is my complete code for reference, it all works until I add the line of code:

                //Creating and Opening a Runspace
            RunspaceConfiguration rsConfig = RunspaceConfiguration.Create();
            PSSnapInException snapInException = null;
            PSSnapInInfo info = rsConfig.AddPSSnapIn(
               "Microsoft.Exchange.Management.PowerShell.Admin",
               out snapInException);
            Runspace myRunSpace = RunspaceFactory.CreateRunspace(rsConfig);
            myRunSpace.Open();

            //How Do I Run a Cmdlet?
            //create a new instance of the Pipeline class 
            Pipeline pipeLine = myRunSpace.CreatePipeline();

            //create an instance of the Command class
            // by using the name of the cmdlet that you want to run
            Command myCommand = new Command(txtCommand.Text);

            //add the command to the Commands collection of the pipeline
            pipeLine.Commands.Add(myCommand);

            Collection<PSObject> commandResults = pipeLine.Invoke();

            // iterate through the commandResults collection
            // and get the name of each cmdlet
            txtResult.Text = "start ....";
            foreach (PSObject cmdlet in commandResults)
            {
                string cmdletName = cmdlet.Properties["Name"].Value.ToString();
                System.Diagnostics.Debug.Print(cmdletName);
                txtResult.Text += "cmdletName: " + cmdletName;
            }
            txtResult.Text += ".... end";
+1  A: 

I don't know for sure, but Exchange 2010 powershell might be implemented as a powershell 2.0 module, which is loaded in a different manner. To find out, go to a system with the exchange management shell on it, and fire it up. Next, run:

ps> get-module

This will list the loaded v2 modules. I would expect the exchange one to appear if you have started the dedicated exchange management shell. If you loaded the regular powershell console, try:

ps> get-module -list

This will list all modules available to load. If you spot the right one, then you'll need to build your code against the v2 system.management.automation dll. For reasons beyond the scope of this reply, v2 powershell's assembly has the same strong name as v1's, so you cannot easily have both versions of powershell on the same machine. Build this from a machine with v2 powershell installed:

InitialSessionState initial = InitialSessionState.CreateDefault();
initialSession.ImportPSModule(new[] { *modulePathOrModuleName* });
Runspace runspace = RunspaceFactory.CreateRunspace(initial);
runspace.Open();
RunspaceInvoke invoker = new RunspaceInvoke(runspace);
Collection<PSObject> results = invoker.Invoke(*myScript*);

Hope this helps,

-Oisin

x0n
A: 

After a lot of trial and error, I finally figured this out. The problem with the code above is it works great when run against Exchange 2007 but things have changed in Exchange 2010. Instead of the snapin called "Microsoft.Exchange.Management.PowerShell.Admin", use this snapin, "Microsoft.Exchange.Management.PowerShell.E2010".

The complete code to run a Powershell command from C# looks like this. Hope this helps someone else trying to do this.

You will need references to System.Management.Automation.Runspaces, System.Collections.ObjectModel and System.Management.Automation also.

I found that the reference to System.Management.Automation had to be manually added to the csproj file itself in the ItemGroup section using notepad like this:

  <Reference Include="System.Management.Automation" />

code below:

private class z_test
{
    //set up
    private RunspaceConfiguration rsConfig = RunspaceConfiguration.Create();
    private PSSnapInException snapInException = null;
    private Runspace runSpace;

    private void RunPowerShell()
    {
        //create the runspace
        runSpace = RunspaceFactory.CreateRunspace(rsConfig);
        runSpace.Open();
        rsConfig.AddPSSnapIn("Microsoft.Exchange.Management.PowerShell.E2010", out snapInException);

        //set up the pipeline to run the powershell command 
        Pipeline pipeLine = runSpace.CreatePipeline();

        //create the script to run
        String sScript = "get-mailbox -identity 'rj'";

        //invoke the command
        pipeLine.Commands.AddScript(sScript);

        Collection<PSObject> commandResults = pipeLine.Invoke();

        //loop through the results of the command and load the SamAccountName into the list
        foreach (PSObject results in commandResults)
        {
            Console.WriteLine(results.Properties["SamAccountName"].Value.ToString());
        }

        pipeLine.Dispose();

        runSpace.Close();
    }
}
RJ