Professional Windows PowerShell Programming

Arul Kumaravel, Jon White, Michael Naixin Li, Scott Happell, Guohui Xie

Mentioned 2

Describes the concepts, components, and development techniques of Windows PowerShell to enable users to build software packages and applications.

More on Amazon.com

Mentioned in questions and answers.

I was listening to the podcast about PowerShell 2.0 that Scott Hanselman did. In that episode, they talked about the possibilities to extend your application to expose functionality for PowerShell.

Now this sounds interesting. Have any of you done such extensions that exposes functionality in your application? If so, what kind of functionallity?

EDIT: To be more precise: I am not interested in hosting PowerShell in my application. I'm more interested in opening up my application with an API-like interface. So a PowerShell Provider seems to be the technology I'm looking for more insight in.

Here's a good book on this side of powershell (which doesn't get much coverage in most books).

Professional Poweshell Programming

Using this book (and some trips to msdn), I was able to have a custom powershell host up and runnning in a day. A few days later, I had custom cmdlets that interact with the gui (to build treeviews, grids, diagrams, menus, etc.)

I have some PowerShell hosts in C# from where I execute PowerShell script code. The code below is from a host in an Add0In for Visual Studio. Problem is that if an error occurs in the PowerShell script code that I don't know the file and line number of the PowerShell script file where the error occured.

My hosting code looks like:

        public Exception Execute(string scriptcode, Hashtable variables)
    {
        Runspace runspace = null;
        Pipeline pipeline = null;
        PipelineStateInfo info = null;

        try
        {
            // Make our output window active
            Logger.ShowOutputWindow();

            // Create the runspace and stuff.
            runspace = RunspaceFactory.CreateRunspace(host);
            pipeline = runspace.CreatePipeline();

            runspace.Open();

            // Add our scriptcode to the pipeline
            pipeline.Commands.Add(new Command(scriptcode, true));

            // We don't want to get PSObjects out of the pipeline, output result as string in default way
            pipeline.Commands.Add(new Command("Out-Default", true));

            // Set up global variables
            FillVariables(runspace, variables);

            SetUpOutputStreams(pipeline);


            // Run the scriptcode
            Collection<PSObject> psOutput = pipeline.Invoke();

            // Did it complete ok?
            info = pipeline.PipelineStateInfo;
            if (info.State != PipelineState.Completed)
            {
                return info.Reason;
            }
            else
            {
                return null; // succesful!
            }
        }
        catch (Exception ex)
        {
            return ex;
        }
    }

First I had my script in the scriptcode variable, I now write the code to a temporary .ps1 file first so I could report on linenumbers in that file. But I can't find how to execute code in a file so it is possible to retrieve filename and line numbers in case of errors.

Any ideas?

This should get you in the right place:

//invoke pipeline
collection = pipeline.Invoke();

// check for errors (non-terminating)
if (pipeline.Error.Count > 0)
{
  //iterate over Error PipeLine until end
  while (!pipeline.Error.EndOfPipeline)
  {
    //read one PSObject off the pipeline
    var value = pipeline.Error.Read() as PSObject;
    if (value != null)
    {
      //get the ErrorRecord
      var r = value.BaseObject as ErrorRecord;
      if (r != null)
      {
        //build whatever kind of message your want
        builder.AppendLine(r.InvocationInfo.MyCommand.Name + " : " + r.Exception.Message);
        builder.AppendLine(r.InvocationInfo.PositionMessage);
        builder.AppendLine(string.Format("+ CategoryInfo: {0}", r.CategoryInfo));
        builder.AppendLine(
        string.Format("+ FullyQualifiedErrorId: {0}", r.FullyQualifiedErrorId));
      }
    }
  }
  return builder.ToString();
}

UPDATE:

As well as the information I wrote in the comment, please also look at this book: Professional PowerShell Programming

I found this book invaluable when I first started programming a host for the PowerShell runtime. It was written by some of the PowerShell devs.

Realated tags

c#powershell