Problem
You want to provide your users with an easy way to automate your program, but don’t want to write a scripting language on your own.
Discussion
One of the fascinating aspects of PowerShell is how easily it lets you add many of its capabilities to your own program. This is because PowerShell is, at its core, a powerful engine that any application can use. The PowerShell console application is in fact just a textbased interface to this engine.
While a full discussion of the PowerShell hosting model is outside the scope of this book, the following example illustrates the techniques behind exposing features of your application for your users to script.
To frame Example 1513, imagine an email application that lets you run rules when it receives an email. While you will want to design a standard interface that allows users to create simple rules, you will also want to provide a way for users to write incredibly complex rules. Rather than design a scripting language yourself, you can simply use PowerShell’s scripting language. In the following example, we provide userwritten scripts with a variable called $message that represents the current message and then runs their commands.
PS >GetContent VerifyCategoryRule.ps1
if($message.Body match "book")
{
[Console]::WriteLine("This is a message about the book.")
}
else
{
[Console]::WriteLine("This is an unknown message.")
}
PS >.\RulesWizardExample.exe (ResolvePath VerifyCategoryRule.ps1)
This is a message about the book.
For more information on how to host PowerShell in your own application, see the MSDN topic, “How to Create a Windows PowerShell Hosting Application,” available at http://msdn2.microsoft.com/enus/library/ms714661.aspx.
Step 1: Download the Windows SDK
The Windows SDK contains samples, tools, reference assemblies, templates, documentation, and other information used when developing PowerShell cmdlets. It is available by searching for “Microsoft Windows SDK” on http://download.microsoft.com .
Step 2: Create a file to hold the hosting source code
Create a file called RulesWizardExample.cs with the content from Example 1513, and save it on your hard drive.
Example 1513. RulesWizardExample.cs
using System; using System.Management.Automation; using System.Management.Automation.Runspaces;
namespace Template
{ // Define a simple class that represents a mail message public class MailMessage {
public MailMessage(string to, string from, string body)
{ this.To = to; this.From = from; this.Body = body;
}
public String To; public String From; public String Body;
}
public class RulesWizardExample
{ public static void Main(string[] args) {
// Ensure that they've provided some script text if(args.Length == 0) {
Console.WriteLine("Usage:"); Console.WriteLine(" RulesWizardExample <script text>"); return;
}
// Create an example message to pass to our rules wizard MailMessage mailMessage =
new MailMessage( "guide_feedback@LeeHolmes.com", "guide_reader@example.com", "This is a message about your book.");
// Create a runspace, which is the environment for // running commands Runspace runspace = RunspaceFactory.CreateRunspace(); runspace.Open();
// Create a variable, called "$message" in the Runspace, and populate // it with a reference to the current message in our application.
Example 1513. RulesWizardExample.cs (continued)
// Pipeline commands can interact with this object like any other // .Net object. runspace.SessionStateProxy.SetVariable("message", mailMessage);
// Create a pipeline, and populate it with the script given in the // first command line argument. Pipeline pipeline = runspace.CreatePipeline(args[0]);
// Invoke (execute) the pipeline, and close the runspace. pipeline.Invoke(); runspace.Close();
} } }
Step 3: Compile and run the example
Although the example itself provides very little functionality, it demonstrates the core concepts behind adding PowerShell scripting to your own program.
SetAlias csc $env:WINDIR\Microsoft.NET\Framework\v2.0.50727\csc.exe $dll = [PsObject].Assembly.Location Csc RulesWizardExample.cs /reference:$dll RulesWizardExample.exe <script commands to run>
For example,
PS >.\RulesWizardExample.exe '[Console]::WriteLine($message.From)' guide_reader@example.com