<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://bartdesmet.net/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>B# .NET Blog : IronRuby</title><link>http://bartdesmet.net/blogs/bart/archive/tags/IronRuby/default.aspx</link><description>Tags: IronRuby</description><dc:language>en</dc:language><generator>CommunityServer 2007 (Build: 20423.869)</generator><item><title>Windows PowerShell through IronRuby - Writing a custom PSHost</title><link>http://bartdesmet.net/blogs/bart/archive/2008/07/06/windows-powershell-through-ironruby-writing-a-custom-pshost.aspx</link><pubDate>Sun, 06 Jul 2008 08:00:00 GMT</pubDate><guid isPermaLink="false">863c5522-913f-4a64-ac0a-bd5f05abad0f:13745</guid><dc:creator>bart</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://bartdesmet.net/blogs/bart/rsscomments.aspx?PostID=13745</wfw:commentRss><comments>http://bartdesmet.net/blogs/bart/archive/2008/07/06/windows-powershell-through-ironruby-writing-a-custom-pshost.aspx#comments</comments><description>&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;Lately I&amp;#39;ve been playing quite a bit with DLR technologies, including &lt;a href="http://www.ironruby.com/"&gt;IronRuby&lt;/a&gt;. During some experiments I came to the conclusion that the Kernel.` method isn&amp;#39;t implemented yet in the current version. This `backtick` method allows executing OS commands from inside a Ruby program. It&amp;#39;s a bit like Process.Start, redirecting the standard output as a string to the Ruby program for further use (actually the Kernel.exec method is precisely implemented like this).&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;img style="BORDER-TOP-WIDTH:0px;BORDER-LEFT-WIDTH:0px;BORDER-BOTTOM-WIDTH:0px;BORDER-RIGHT-WIDTH:0px;" height="340" alt="image" src="http://bartdesmet.info/images_wlw/WindowsPowerShellthroughIronRuby_12D6E/image_thumb.png" width="677" border="0" /&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;One thing I like about the NotImplementedException is the fact it points unambiguously to the source that&amp;#39;s missing :-). Indeed, if you browse the IronRuby source, you&amp;#39;ll find this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[&lt;font color="#008080"&gt;RubyMethod&lt;/font&gt;(&lt;font color="#800000"&gt;&amp;quot;`&amp;quot;&lt;/font&gt;, &lt;font color="#008080"&gt;RubyMethodAttributes&lt;/font&gt;.PrivateInstance)] &lt;br /&gt;[&lt;font color="#008080"&gt;RubyMethod&lt;/font&gt;(&lt;font color="#800000"&gt;&amp;quot;`&amp;quot;&lt;/font&gt;, &lt;font color="#008080"&gt;RubyMethodAttributes&lt;/font&gt;.PublicSingleton)] &lt;br /&gt;&lt;font color="#0000ff"&gt;public static &lt;/font&gt;&lt;font color="#008080"&gt;MutableString &lt;/font&gt;ExecuteCommand(&lt;font color="#008080"&gt;CodeContext&lt;/font&gt;&lt;font color="#008000"&gt;/*!*/ &lt;/font&gt;context, &lt;font color="#0000ff"&gt;object &lt;/font&gt;self, [&lt;font color="#008080"&gt;NotNull&lt;/font&gt;]&lt;font color="#008080"&gt;MutableString&lt;/font&gt;&lt;font color="#008000"&gt;/*!*/&lt;/font&gt; command) { &lt;br /&gt;&lt;font color="#008000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // TODO:&lt;/font&gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;throw new &lt;/font&gt;&lt;font color="#008080"&gt;NotImplementedException&lt;/font&gt;(); &lt;br /&gt;}&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Actually there are a couple of things here that are worth to discuss besides the current void of the method body:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Strings in Ruby are mutable as opposed to strings in the CLR/BCL. Therefore they are wrapped in a MutableString class. &lt;/li&gt;
&lt;li&gt;The weird /*!*/ notation indicates not-nullness, mirrored after the equivalent uncommented form in Spec# (e.g. MutableString! means a null-nullable string). To work with regular C#, the NotNullAttribute is used. &lt;/li&gt;
&lt;li&gt;Methods like this one are not invoked by Ruby directly, instead the RubyMethodAttribute declaration carries the metadata that provides the entry-point to the method (as well as other metadata). &lt;/li&gt;&lt;/ul&gt;
&lt;h1&gt;Kernel.`&lt;/h1&gt;
&lt;p&gt;I won&amp;#39;t cover the differences between Kernel.`, Kernel.system and Kernel.exec; more information can be found &lt;a href="http://www.ruby-doc.org/core/classes/Kernel.html"&gt;here&lt;/a&gt;. The backtick one is our target for the scope of this post:&lt;/p&gt;
&lt;p&gt;&lt;a class="" title="M001111" name="M001111"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href="http://www.ruby-doc.org/Kernel.src/M001111.html"&gt;&lt;em&gt;`cmd` =&amp;gt; string &lt;br /&gt;&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Returns the standard output of running cmd in a subshell. The built-in syntax %x{…} uses this method. Sets $? to the process status. &lt;/em&gt;&lt;/p&gt;&lt;pre&gt;&lt;em&gt;   `date`                   #=&amp;gt; &amp;quot;Wed Apr  9 08:56:30 CDT 2003\n&amp;quot;
   `ls testdir`.split[1]    #=&amp;gt; &amp;quot;main.rb&amp;quot;
   `echo oops &amp;amp;&amp;amp; exit 99`   #=&amp;gt; &amp;quot;oops\n&amp;quot;
   $?.exitstatus            #=&amp;gt; 99&lt;/em&gt;&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;Actually I want to focus on (yet another) powerful feature in PowerShell, namely the ability to create &lt;strong&gt;custom hosts&lt;/strong&gt;. What we want to achieve here is that the backtick syntax (or the equivalent %x syntax) runs the specified command as a PowerShell command (or pipeline of multiple cmdlets), emitting the string output as the `&amp;#39;s methods return value. Notice though this actually downgrades ones of the core principles of PowerShell concerning the use of objects through the pipeline rather than falling back to strings. One could easily think of a more powerful way to expose the results of a PowerShell invocation as PSObjects in Ruby but we&amp;#39;ll keep that for later.&lt;/p&gt;
&lt;p&gt;&lt;font color="#ff0000"&gt;&lt;u&gt;Important:&lt;/u&gt; This post outlines no more than the capability to hook up PowerShell in IronRuby through Kernel.`. Obviously no promises are made about the way Kernel.` will eventually be implemented in IronRuby as we move forward.&lt;/font&gt;&lt;/p&gt;
&lt;h1&gt;Building a custom PS host&lt;/h1&gt;
&lt;p&gt;Creating custom PS hosts isn&amp;#39;t that hard, depending on how much functionality you want to take over. We&amp;#39;ll stick with the basics of console I/O, actually just the O in this. What we want to get done is this:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Build up a runspace containing the command passed to Kernel.` (in addition to some more pipeline commands to produce the right output, see further). &lt;/li&gt;
&lt;li&gt;Invoke the built-up pipeline. &lt;/li&gt;
&lt;li&gt;Retrieve the string output from the host, concatenate it into one big string and return that one to the caller of Kernel.`. &lt;/li&gt;&lt;/ol&gt;
&lt;h2&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2&gt;Preparing for PowerShell programming&lt;/h2&gt;
&lt;p&gt;In order to extend PowerShell, you&amp;#39;ll need to add a reference to System.Management.Automation.dll which can be found in the Reference Assemblies folder (click to enlarge):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href="http://bartdesmet.info/images_wlw/WindowsPowerShellthroughIronRuby_12D6E/image.png"&gt;&lt;img style="BORDER-TOP-WIDTH:0px;BORDER-LEFT-WIDTH:0px;BORDER-BOTTOM-WIDTH:0px;BORDER-RIGHT-WIDTH:0px;" height="128" alt="image" src="http://bartdesmet.info/images_wlw/WindowsPowerShellthroughIronRuby_12D6E/image_thumb_3.png" width="244" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;/blockquote&gt;
&lt;h2&gt;Runspaces&lt;/h2&gt;
&lt;p&gt;Let&amp;#39;s start at the very top by implementing a method called &amp;quot;InvokePS&amp;quot; that sets up the infrastructure to call PowerShell:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;font color="#0000ff"&gt;public static class&lt;/font&gt; RubyToPS &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;public static string &lt;/font&gt;InvokePS(&lt;font color="#0000ff"&gt;string &lt;/font&gt;command) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#008080"&gt;RubyPSHost &lt;/font&gt;host = &lt;font color="#0000ff"&gt;new &lt;/font&gt;&lt;font color="#008080"&gt;RubyPSHost&lt;/font&gt;(); &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;using &lt;/font&gt;(&lt;font color="#008080"&gt;Runspace &lt;/font&gt;runspace = &lt;font color="#008080"&gt;RunspaceFactory&lt;/font&gt;.CreateRunspace(host)) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; runspace.Open(); &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;using &lt;/font&gt;(&lt;font color="#008080"&gt;Pipeline &lt;/font&gt;pipeline = runspace.CreatePipeline()) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pipeline.Commands.AddScript(command); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pipeline.Commands[0].MergeMyResults(&lt;font color="#008080"&gt;PipelineResultTypes&lt;/font&gt;.Error, &lt;font color="#008080"&gt;PipelineResultTypes&lt;/font&gt;.Output);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pipeline.Commands.Add(&lt;font color="#800000"&gt;&amp;quot;out-default&amp;quot;&lt;/font&gt;); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pipeline.Invoke(); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;return&lt;/font&gt; ((&lt;font color="#008080"&gt;RubyPSHostUserInterface&lt;/font&gt;)host.UI).Output; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;}&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;The RubyPSHost class will be shown next, let&amp;#39;s focus on the Runspace stuff for now. A runspace serves as the entry-point to the PowerShell engine and encapsulates all the state needed to execute pipelines. Once we&amp;#39;ve opened the runspace, a pipeline is created to which we add the passed-in command as a script. This allows more than just one cmdlet invocation to be executed (e.g. &amp;quot;gps | where { $_.WorkingSet64 -gt 50MB }&amp;quot;). To send output to the host we append Out-Default to the pipeline:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;NAME &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Out-Default &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;SYNOPSIS &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Send the output to the default formatter and the default output cmdlet. Thi &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; s cmdlet has no effect on the formatting or output. It is a placeholder tha &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; t lets you write your own Out-Default function or cmdlet. &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;SYNTAX &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Out-Default [-inputObject &amp;lt;psobject&amp;gt;] [&amp;lt;CommonParameters&amp;gt;] &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;DETAILED DESCRIPTION &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; The Out-Default cmdlet send the output to the default formatter and the def &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ault output cmdlet. This cmdlet has no effect on the formatting or output. &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; It is a placeholder that lets you write your own Out-Default function or cm &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; dlet.&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;The &lt;a href="http://msdn.microsoft.com/en-us/library/system.management.automation.runspaces.command.mergemyresults(VS.85).aspx"&gt;MergeMyResults&lt;/a&gt; call is used to ensure that error objects produced by the first command are merged into the output (otherwise you&amp;#39;ll get an exception instead). Finally the output is retrieved from the host after invoking the pipeline. How this works will be covered in a minute.&lt;/p&gt;
&lt;p&gt;To read more about PowerShell runspaces, check out &lt;a href="http://community.bartdesmet.net/blogs/bart/search.aspx?q=powershell+runspace"&gt;my other posts on the topic&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Deriving from PSHost&lt;/h2&gt;
&lt;p&gt;Custom PowerShell hosts derive from the abstract PSHost base class. There&amp;#39;s quite some stuff that can be done here but we&amp;#39;ll stick with the absolute minimum functionality required to reach our goals:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;font color="#0000ff"&gt;internal class&lt;/font&gt; &lt;font color="#008080"&gt;RubyPSHost &lt;/font&gt;: &lt;font color="#008080"&gt;PSHost&lt;/font&gt; &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;private&lt;/font&gt; &lt;font color="#008080"&gt;Guid &lt;/font&gt;_hostId = &lt;font color="#008080"&gt;Guid&lt;/font&gt;.NewGuid(); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;strong&gt;&lt;font color="#0000ff"&gt;private&lt;/font&gt; &lt;font color="#008080"&gt;RubyPSHostUserInterface &lt;/font&gt;_ui = &lt;font color="#0000ff"&gt;new &lt;/font&gt;&lt;font color="#008080"&gt;RubyPSHostUserInterface&lt;/font&gt;(); &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;public override&lt;/font&gt; &lt;font color="#008080"&gt;Guid&lt;/font&gt; InstanceId &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;get&lt;/font&gt; { &lt;font color="#0000ff"&gt;return &lt;/font&gt;_hostId; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;public override string &lt;/font&gt;Name &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;get&lt;/font&gt; { &lt;font color="#0000ff"&gt;return &lt;/font&gt;&lt;font color="#800000"&gt;&amp;quot;RubyPSHost&amp;quot;&lt;/font&gt;; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;public override &lt;/font&gt;&lt;font color="#008080"&gt;Version&lt;/font&gt; Version &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;get&lt;/font&gt; { &lt;font color="#0000ff"&gt;return new &lt;/font&gt;&lt;font color="#008080"&gt;Version&lt;/font&gt;(1, 0); } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;public override &lt;/font&gt;&lt;font color="#008080"&gt;PSHostUserInterface&lt;/font&gt; UI &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;get&lt;/font&gt; { &lt;font color="#0000ff"&gt;return &lt;/font&gt;_ui; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/strong&gt; &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;public override &lt;/font&gt;&lt;font color="#008080"&gt;CultureInfo &lt;/font&gt;CurrentCulture &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;get&lt;/font&gt; { &lt;font color="#0000ff"&gt;return &lt;/font&gt;&lt;font color="#008080"&gt;Thread&lt;/font&gt;.CurrentThread.CurrentCulture; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;public override &lt;/font&gt;&lt;font color="#008080"&gt;CultureInfo &lt;/font&gt;CurrentUICulture &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;get&lt;/font&gt; { &lt;font color="#0000ff"&gt;return &lt;/font&gt;&lt;font color="#008080"&gt;Thread&lt;/font&gt;.CurrentThread.CurrentUICulture; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;public override void&lt;/font&gt; EnterNestedPrompt() &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;throw new &lt;/font&gt;&lt;font color="#008080"&gt;NotImplementedException&lt;/font&gt;(); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;public override void&lt;/font&gt; ExitNestedPrompt() &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;throw new &lt;/font&gt;&lt;font color="#008080"&gt;NotImplementedException&lt;/font&gt;(); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;public override void&lt;/font&gt; NotifyBeginApplication() &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;return&lt;/font&gt;; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;public override void&lt;/font&gt; NotifyEndApplication() &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;return&lt;/font&gt;; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;public override void&lt;/font&gt; SetShouldExit(&lt;font color="#0000ff"&gt;int&lt;/font&gt; exitCode) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;return&lt;/font&gt;; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;}&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;More information about all of those methods and properties can be found on &lt;a href="http://msdn.microsoft.com/en-us/library/system.management.automation.host.pshost(VS.85).aspx"&gt;MSDN&lt;/a&gt;. The most important one to us the the UI property that points at our PSHostUserInterface implementation called &lt;strong&gt;RubyPSHostUserInterface&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;Implementing PSHostUserInterface&lt;/h2&gt;
&lt;p&gt;Where the PSHost class provides basic information concerning the metadata of the host (name, version, id)m lifetime of the host (nested prompt, execit commands) and general settings (cultures), the &lt;a href="http://msdn.microsoft.com/en-us/library/system.management.automation.host.pshostuserinterface(VS.85).aspx"&gt;PSHostUserInterface&lt;/a&gt; class deals with &lt;em&gt;&amp;quot;dialog-oriented and line-oriented interaction between the cmdlet and the user, such as writing to, prompting for, and reading from user input&amp;quot;&lt;/em&gt; (from MSDN). The part we&amp;#39;re interested in the &lt;em&gt;writing to&lt;/em&gt; part. We won&amp;#39;t deal with prompts or user interaction - if one wants to do this, the Kernel.` command is no longer non-interactive (a possible alternative way to implement this would be to spawn PowerShell.exe and just get the shell&amp;#39;s output here - the default host would take care of all user interaction if required; the only problem is that prompts would appear in the Kernel.` output as well). Implementation of this class isn&amp;#39;t that hard either:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;font color="#0000ff"&gt;internal class&lt;/font&gt; &lt;font color="#008080"&gt;RubyPSHostUserInterface &lt;/font&gt;: &lt;font color="#008080"&gt;PSHostUserInterface&lt;/font&gt; &lt;br /&gt;{ &lt;br /&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;private&lt;/font&gt; &lt;font color="#008080"&gt;StringBuilder&lt;/font&gt; _sb; &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;public&lt;/font&gt; RubyPSHostUserInterface() &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _sb = &lt;font color="#0000ff"&gt;new&lt;/font&gt; &lt;font color="#008080"&gt;StringBuilder&lt;/font&gt;(); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;public override void&lt;/font&gt; Write(&lt;font color="#008080"&gt;ConsoleColor &lt;/font&gt;foregroundColor, &lt;font color="#008080"&gt;ConsoleColor&lt;/font&gt; backgroundColor, &lt;font color="#0000ff"&gt;string&lt;/font&gt; value) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _sb.Append(value); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;public override void&lt;/font&gt; Write(&lt;font color="#0000ff"&gt;string&lt;/font&gt; value) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _sb.Append(value); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;public override void&lt;/font&gt; WriteDebugLine(&lt;font color="#0000ff"&gt;string &lt;/font&gt;message) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _sb.AppendLine(&lt;font color="#800000"&gt;&amp;quot;DEBUG: &amp;quot;&lt;/font&gt; + message); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;public override void&lt;/font&gt; WriteErrorLine(&lt;font color="#0000ff"&gt;string&lt;/font&gt; value) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _sb.AppendLine&lt;font color="#800000"&gt;(&amp;quot;ERROR: &amp;quot;&lt;/font&gt; + value); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;public override void&lt;/font&gt; WriteLine(&lt;font color="#0000ff"&gt;string&lt;/font&gt; value) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _sb.AppendLine(value); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;public override void&lt;/font&gt; WriteVerboseLine(&lt;font color="#0000ff"&gt;string &lt;/font&gt;message) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _sb.AppendLine(&lt;font color="#800000"&gt;&amp;quot;VERBOSE: &amp;quot;&lt;/font&gt; + message); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;public override void&lt;/font&gt; WriteWarningLine(&lt;font color="#0000ff"&gt;string &lt;/font&gt;message) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _sb.AppendLine(&lt;font color="#800000"&gt;&amp;quot;WARNING: &amp;quot;&lt;/font&gt; + message); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;public override void&lt;/font&gt; WriteProgress(&lt;font color="#0000ff"&gt;long&lt;/font&gt; sourceId, &lt;font color="#008080"&gt;ProgressRecord&lt;/font&gt; record) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;return&lt;/font&gt;; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;public string&lt;/font&gt; Output &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;get&lt;/font&gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;return&lt;/font&gt; _sb.ToString(); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/strong&gt; &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;public override&lt;/font&gt; &lt;font color="#008080"&gt;Dictionary&lt;/font&gt;&amp;lt;&lt;font color="#0000ff"&gt;string&lt;/font&gt;, &lt;font color="#008080"&gt;PSObject&lt;/font&gt;&amp;gt; Prompt(&lt;font color="#0000ff"&gt;string&lt;/font&gt; caption, &lt;font color="#0000ff"&gt;string &lt;/font&gt;message, System.Collections.ObjectModel.&lt;font color="#008080"&gt;Collection&lt;/font&gt;&amp;lt;&lt;font color="#008080"&gt;FieldDescription&lt;/font&gt;&amp;gt; descriptions) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;throw new&lt;/font&gt; &lt;font color="#008080"&gt;NotImplementedException&lt;/font&gt;(); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;public override&lt;/font&gt; &lt;font color="#0000ff"&gt;int&lt;/font&gt; PromptForChoice(&lt;font color="#0000ff"&gt;string&lt;/font&gt; caption, &lt;font color="#0000ff"&gt;string&lt;/font&gt; message, System.Collections.ObjectModel.&lt;font color="#008080"&gt;Collection&lt;/font&gt;&amp;lt;&lt;font color="#008080"&gt;ChoiceDescription&lt;/font&gt;&amp;gt; choices, &lt;font color="#0000ff"&gt;int&lt;/font&gt; defaultChoice) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;throw new&lt;/font&gt; &lt;font color="#008080"&gt;NotImplementedException&lt;/font&gt;(); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;public override&lt;/font&gt; &lt;font color="#008080"&gt;PSCredential&lt;/font&gt; PromptForCredential(&lt;font color="#0000ff"&gt;string&lt;/font&gt; caption, &lt;font color="#0000ff"&gt;string&lt;/font&gt; message, &lt;font color="#0000ff"&gt;string&lt;/font&gt; userName, &lt;font color="#0000ff"&gt;string&lt;/font&gt; targetName, &lt;font color="#008080"&gt;PSCredentialTypes&lt;/font&gt; allowedCredentialTypes, &lt;font color="#008080"&gt;PSCredentialUIOptions&lt;/font&gt; options) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;throw new&lt;/font&gt; &lt;font color="#008080"&gt;NotImplementedException&lt;/font&gt;(); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;public override&lt;/font&gt; &lt;font color="#008080"&gt;PSCredential&lt;/font&gt; PromptForCredential(&lt;font color="#0000ff"&gt;string&lt;/font&gt; caption, &lt;font color="#0000ff"&gt;string&lt;/font&gt; message, &lt;font color="#0000ff"&gt;string&lt;/font&gt; userName, &lt;font color="#0000ff"&gt;string&lt;/font&gt; targetName) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;throw new&lt;/font&gt; &lt;font color="#008080"&gt;NotImplementedException&lt;/font&gt;(); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;public override&lt;/font&gt; &lt;font color="#008080"&gt;PSHostRawUserInterface&lt;/font&gt; RawUI &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;get&lt;/font&gt; { &lt;font color="#0000ff"&gt;return null&lt;/font&gt;; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;public override string&lt;/font&gt; ReadLine() &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;throw new&lt;/font&gt; &lt;font color="#008080"&gt;NotImplementedException&lt;/font&gt;(); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;public override &lt;/font&gt;System.Security.&lt;font color="#008080"&gt;SecureString &lt;/font&gt;ReadLineAsSecureString() &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;throw new&lt;/font&gt; &lt;font color="#008080"&gt;NotImplementedException&lt;/font&gt;(); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;}&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;The core of our implementation lies in the fact that all Write* methods emit their data to a StringBuilder instance that aggregates all output sent to the host. This is the data that gets retrieved by our &lt;strong&gt;InvokePS &lt;/strong&gt;method on the last line:&lt;/p&gt;
&lt;blockquote&gt;&lt;font color="#0000ff"&gt;return&lt;/font&gt; ((&lt;font color="#008080"&gt;RubyPSHostUserInterface&lt;/font&gt;)host.UI).&lt;strong&gt;Output&lt;/strong&gt;; &lt;br /&gt;&lt;/blockquote&gt;
&lt;p&gt;Notice this isn&amp;#39;t the absolute end of host-level extensibility in PowerShell. A PSHostUserInterface class can point at a PSHost&lt;strong&gt;Raw&lt;/strong&gt;UserInterface object that controls host window characteristics (such as the size, position and title of the window). Actually it would be interesting to implement this one as well in order to provide an accurate BufferSize that will be used by PowerShell to control the maximum length of individual lines before wrapping to the next line. The reason this would be a good idea is that screen-scraping Ruby programs should be able to ignore different wrapping behavior depending on the hosting command window (which would cause programs to behave differently depending where they run). Ideally there would be no wrapping at all (letting the DLR IronRuby command-line host dealing with wrapping when printing data to the screen). I&amp;#39;ll leave this exercise to the reader.&lt;/p&gt;
&lt;h2&gt;Hooking it up&lt;/h2&gt;
&lt;p&gt;All of the above has been implemented in a separate &lt;u&gt;strong-named&lt;/u&gt; Class Library which I&amp;#39;m just referencing in the IronRuby.Libraries project. This is actually very &lt;u&gt;quick-and-dirty&lt;/u&gt;, making IronRuby directly dependent on our assembly and by extension Windows PowerShell. A way around this would be to load the assembly dynamically possibly based on an environment variable. There are lots of possibilities here which we consider just an implementation detail for now. The only thing left to do is to call our InvokePS method which requires some conversions between System.String and MutableString:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[&lt;font color="#008080"&gt;RubyMethod&lt;/font&gt;(&lt;font color="#800000"&gt;&amp;quot;`&amp;quot;&lt;/font&gt;, &lt;font color="#008080"&gt;RubyMethodAttributes&lt;/font&gt;.PrivateInstance)] &lt;br /&gt;[&lt;font color="#008080"&gt;RubyMethod&lt;/font&gt;(&lt;font color="#800000"&gt;&amp;quot;`&amp;quot;&lt;/font&gt;, &lt;font color="#008080"&gt;RubyMethodAttributes&lt;/font&gt;.PublicSingleton)] &lt;br /&gt;&lt;font color="#0000ff"&gt;public static &lt;/font&gt;&lt;font color="#008080"&gt;MutableString &lt;/font&gt;ExecuteCommand(&lt;font color="#008080"&gt;CodeContext&lt;/font&gt;&lt;font color="#008000"&gt;/*!*/ &lt;/font&gt;context, &lt;font color="#0000ff"&gt;object &lt;/font&gt;self, [&lt;font color="#008080"&gt;NotNull&lt;/font&gt;]&lt;font color="#008080"&gt;MutableString&lt;/font&gt;&lt;font color="#008000"&gt;/*!*/&lt;/font&gt; command) {&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;return &lt;/font&gt;&lt;font color="#008080"&gt;MutableString&lt;/font&gt;.Create(&lt;font color="#008080"&gt;RubyToPS&lt;/font&gt;.InvokePS(command.ConvertToString())); &lt;br /&gt;}&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;That&amp;#39;s it! Here&amp;#39;s the result:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href="http://bartdesmet.info/images_wlw/WindowsPowerShellthroughIronRuby_12D6E/image_3.png"&gt;&lt;img style="BORDER-TOP-WIDTH:0px;BORDER-LEFT-WIDTH:0px;BORDER-BOTTOM-WIDTH:0px;BORDER-RIGHT-WIDTH:0px;" height="328" alt="image" src="http://bartdesmet.info/images_wlw/WindowsPowerShellthroughIronRuby_12D6E/image_thumb_4.png" width="701" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;u&gt;Note: &lt;/u&gt;The \r\n insertions in the output for display by Ruby&amp;#39;s console cause things to wrap a bit nasty given the default of 80 characters buffer width. I&amp;#39;ve adjusted to 83 characters to make this render correctly. With some smart &amp;quot;Raw UI host&amp;quot; one could eliminate some issues here - however the internal contents of the string is more important since the app will likely rely on that (otherwise you&amp;#39;d simply run a PowerShell interactive shell, wouldn&amp;#39;t you?). Just as one sample, here&amp;#39;s the output of the each_line iterator:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href="http://bartdesmet.info/images_wlw/WindowsPowerShellthroughIronRuby_12D6E/image_4.png"&gt;&lt;img style="BORDER-TOP-WIDTH:0px;BORDER-LEFT-WIDTH:0px;BORDER-BOTTOM-WIDTH:0px;BORDER-RIGHT-WIDTH:0px;" height="256" alt="image" src="http://bartdesmet.info/images_wlw/WindowsPowerShellthroughIronRuby_12D6E/image_thumb_5.png" width="701" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Does look an awful lot like PowerShell, doesn&amp;#39;t it?&lt;/p&gt;
&lt;p&gt;Cheers!&lt;/p&gt;&lt;img src="http://bartdesmet.net/aggbug.aspx?PostID=13745" width="1" height="1"&gt;</description><category domain="http://bartdesmet.net/blogs/bart/archive/tags/Windows+PowerShell/default.aspx">Windows PowerShell</category><category domain="http://bartdesmet.net/blogs/bart/archive/tags/IronRuby/default.aspx">IronRuby</category></item></channel></rss>