Freigeben über


WPF and PowerShell Series: Host Applications and PowerShell API

A great deal has been written about using PowerShell together with WPF, but typically this has meant generating the latter from within the former.  Likewise, even though PowerShell 2.0 introduced some incredibly useful APIs to invoke PowerShell commands from within your applications, most examples found online to date are centered around console-based applications. 

Much less has been written about using PowerShell interactively from within a WPF application – a powerful approach that opens up a wealth of possibilities in your development process.  This series of blog posts will introduce some key concepts required to develop such an application.

Part 1: Host Applications and PowerShell API

If you have run a PowerShell script or written a script in the PowerShell ISE (Integrated Scripting Environment), you have already encountered host applications.  According to MSDN, a host application “is any application that loads the Windows PowerShell engine into its process and uses it to perform operations. This could be a graphical user interface (GUI) that runs Windows PowerShell commands to perform an administrative task, or it could be a console application that provides an interactive session for the user.”

As you might now suspect, two host applications are provided with your PowerShell installation: the default console-based PowerShell.exe and the graphical PowerShell Integrated Scripting Environment (ISE) .  Whereas PowerShell.exe is your traditional shell environment (for those familiar with bash or the Command Prompt), the ISE allows you edit, run and debug scripts in a more IDE-like environment (e.g., Visual Studio, Eclipse).  The ISE included with PowerShell version 3.0, in particular, adds such familiar features as Intellisense to make script authoring easier than ever. 

 
Figure 1. PowerShell.exe  Figure 2. PowerShell Integrated Scripting Environment (ISE)

Beginning with PowerShell 2.0, you and I are now able to write our own custom host interface, using APIs that let you integrate the PS engine into your own applications.

Implementing a custom host is not for everyone; after all, there are already two mature and fully-featured programs for the vast majority of your scripting needs.  But in cases where you wish to extend your application to run PowerShell cmdlets without launching a separate process, or where you wish to add interactive PowerShell power (no pun intended) to your application without needing the overhead of the ISE, this can be a very attractive option.

The Basics

Despite our eventual goal of a WPF graphical interface, I will start our journey with the oft-presented console application.  In order to use the PowerShell runtime in your project, you must have access to the System.Management.Automation namespace.  If you are using Visual Studio, make sure to add a reference to the DLL in your project. 

NOTE: For Windows 7 and Windows 8 users, this DLL is located in X:\Windows\assembly\GAC_MSIL\System.Management.Automation , where X is the drive on which Windows is installed.

 using System.Management.Automation;

One of the simplest applications using the PowerShell engine does the following:

  • Initialize the PowerShell pipeline in the default host
  • Execute a predetermined command
  • Display its output to the console

As you might have noticed, I added another new term in my above description: pipeline. The terminology can be overwhelming, so let me summarize briefly before continuing: a pipeline holds commands or script to be run by the PowerShell engine via a host application.

     class Program
    {
        static void Main(string[] args)
        {
            var pipeline = PowerShell.Create();
 
            pipeline.AddCommand("Get-Command");
 
            foreach (PSObject result in pipeline.Invoke())
            {
                Console.WriteLine("{0,-15}{1,-20}",
                    result.Members["CommandType"].Value,
                    result.Members["Name"].Value
                );
            }
        }
    }

Using the PowerShell.Create() method in the simple application creates a new pipeline that eventually holds our command.  When we invoke (i.e., execute) the pipeline's contents with Invoke(), the console application waits for the pipeline to complete before returning an iterable list of PSObject objects.  These are powerful objects which allow you to access results much as you would in the traditional PowerShell.exe application:

PowerShell.exe PowerShell API (C#)
$object.PropertyName object.Members["PropertyName"].Value

This program may be extremely limited in function, but by successfully running it, you are officially on the path toward our eventual WPF PowerShell snazzy graphical host!

In Part 2 of this series, we will take two further key steps needed to take our application graphical: learn how to invoke a pipeline asynchronously, a must for any modern GUI application, and learn about runspaces.

Comments

  • Anonymous
    June 08, 2013
    Thank you for sharing, and waiting for your next post.

  • Anonymous
    October 03, 2013
    "invoke a pipeline asynchronously" is a key part here. Can we expect 2nd part of this service anytime soon? Thanks.

  • Anonymous
    October 23, 2013
    Hi Phil This is exactly what I have been looking for :) Are the other posts in the series ready? Thanks Ernie

  • Anonymous
    February 17, 2016
    I would love to see this continue...