Automating execution of built-in Exchange 2010 PS1 Scripts through .NET

 

Through the magic of Powershell automation that was introduced for Exchange Management, it so happens that Exchange 2007 and 2010 come with quite a few built-in scripts that attempt to make your life easier, (not to forget all the custom scripts that you could write yourself, to automate tasks that are frequent to you).

While there are several ways of automating execution of Exchange Cmdlets through powershell (documented here [link] for 2007 and here [link] for 2010), there may be scenarios in which all you really want to do is execute a nifty PS1 script that runs very efficiently when executed via Powershell, and all you really need to do is figure out how to execute that PS1 script, you could possibly use this sample [Link].

But sometimes, as it so happens, PS1 scripts refer other resource files, and seem to be dependent on other parameters, which makes them a bit tricky to execute outside of Powershell. For instance, the RedistributeActiveDatabases.ps1 (documentation) which comes with Exchange 2010 SP1, and does a marvellous job of balancing active mailbox database copies across a Database Access Group, really only seems to work when executed directly within the context of Powershell. Coupled with the fact that quite a lot of cmdlets would be executed in a single run through the script, piping each cmdlet to a Remote Powershell runspace would cause the script to take painfully longer to complete.

In such circumstances, the best approach is to automate the loading of the PS1 script through powershell. But how?

Well, it’s quite simple, really, if we go back to the basics. All we need to do is create a process of command prompt and execute powershell.exe through it, providing it the path of the PS1 script as a parameter (appending the parameters to the script in the process), and capturing the output returned.

This is how I managed to execute the elusive RedistributeActiveDatabases.ps1 script, providing my own custom DAG name, and the “ShowDatabaseDistributionByServer” switch to organize the output. In brief, the input to powershell looks something like this:

 RedistributeActiveDatabases.ps1 -DagName DAG1 -ShowDatabaseDistributionByServer

 

The same thing, when executed via C#, giving us the flexibility to modify the DAG name through user-input, would look like this:

 void callPS1Script(dagName)

{

string filePath = Environment.GetEnvironmentVariable("ExchangeInstallPath") + "Scripts\\RedistributeActiveDatabases.ps1";

string command = "powershell.exe -file \"" + filePath + "\" -DagName \"" + dagName + "\" -ShowDatabaseDistributionByServer";

try

{

// Create a ProcessStartInfo object specifying "cmd" as the target program.

// The switch /c tells cmd that the command that follows is to be executed

System.Diagnostics.ProcessStartInfo objPSI = new System.Diagnostics.ProcessStartInfo("cmd", "/c " + command);

                // This specifies that standard output will be redirected to Process.StandardOutput StreamReader.

objPSI.RedirectStandardOutput = true;

objPSI.UseShellExecute = false;

objPSI.CreateNoWindow = true; //Optional: To avoid the window that comes with cmd prompt

// Create a process, assign its ProcessStartInfo and execute

System.Diagnostics.Process objProc = new System.Diagnostics.Process();

objProc.StartInfo = objPSI;

objProc.Start();

// Retrieve output

string objOutput = objProc.StandardOutput.ReadToEnd();

// Display Output

Console.WriteLine(objOutput);

}

catch (Exception e)

{

Console.WriteLine(e.Message);

}

}

 

This was tried out in a ConsoleApp by me, and in an ASP.NET application by the customer I was working with, so it seems good to go. For in-built Exchange Scripts to work, you’ll naturally want Exchange Management Tools for the relevant version of Exchange Server installed.

Cheers!