ConvertTo-ISEAddOn.ps1

function ConvertTo-ISEAddOn
{
    <#
    .Synopsis
        Converts ShowUI to an ISEAddOn
    .Description
        Compiles an ISE Add-on from a ShowUI Script
    .Link
        http://show-ui.org/
 
    #>

    [CmdletBinding(DefaultParameterSetName="CreateOnly")]
    param(
    # The display name of the add-on
    [Parameter(Mandatory=$true,
        ParameterSetName="DisplayNow")]
    [string]$DisplayName,

    # The script block that powers the add-on
    [Parameter(Mandatory=$true,
        ParameterSetName="CreateOnly")]
    [Parameter(Mandatory=$true,
        ParameterSetName="DisplayNow")]
    [ScriptBlock]
    $ScriptBlock,

    # If set, the add-on will be added and displayed vertically
    [Parameter(ParameterSetName="DisplayNow")]
    [switch]
    $AddVertically,

    # If set, the add-on will be added and displayed horizontally
    [Parameter(ParameterSetName="DisplayNow")]
    [switch]
    $AddHorizontally,
    
    [Switch]
    $AddFloating,
   

    # If set, the add-on will be added, but not shown
    [Parameter(Mandatory=$true,
        ParameterSetName="DisplayNow")]
    [switch]
    $DoNotShow,

    # If set, any hooks for the add-on will be removed. Use this to reload add-ons
    [Switch]
    $Force,

    # Suggestions for a shortcut key to use for the Add-On
    [string[]]
    $ShortcutKey
    )

    begin {
<# if ($psVersionTable.PSVersion -lt "3.0") {
            Write-Warning "Ise Window Add ons were not added until version 3.0."
            return
        }#>

    }

    process {
$addOnNumber = Get-Random
$addOnType =@"
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Data;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Threading;
using System.Windows.Threading;
using System.ComponentModel;
using System.Collections.Generic;
using System.Collections;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using Microsoft.PowerShell.Host.ISE;
using System.Windows.Input;
using System.Text;
using System.Threading;
using System.Windows.Threading;
 
namespace ShowISEAddOns
{
 
 
 
    public class ShowUIIseAddOn${addOnNumber} : UserControl $(if ($psVersionTable.psversion -ge '3.0') { ', IAddOnToolHostObject' })
    {
 
        ObjectModelRoot hostObject;
             
        #region IAddOnToolHostObject Members
 
 
     
        public ObjectModelRoot HostObject
        {
            get
            {
                return this.hostObject;
            }
            set
            {
                this.hostObject = value;
                this.mainRunspace = Runspace.DefaultRunspace;
                this.hostObject.CurrentPowerShellTab.PropertyChanged += new PropertyChangedEventHandler(CurrentPowerShellTab_PropertyChanged);
            }
        }
 
        private void CurrentPowerShellTab_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (this.hostObject.CurrentPowerShellTab.CanInvoke) {
                if (this.Content != null && this.Content is UIElement ) {
                    (this.Content as UIElement).IsEnabled = true;
                }
            }
        }
        #endregion IAddOnToolHostObject
        private Runspace mainRunspace;
 
        public Runspace MainRunspace
        {
            get {
                return mainRunspace;
            }
            set {
                mainRunspace = value;
            }
        }
     
        public ShowUIIseAddOn${addOnNumber}() {
            if (Runspace.DefaultRunspace == null ||
                Runspace.DefaultRunspace.ApartmentState != System.Threading.ApartmentState.STA ||
                Runspace.DefaultRunspace.ThreadOptions != PSThreadOptions.UseCurrentThread) {
                InitialSessionState iss = InitialSessionState.CreateDefault();
                iss.ImportPSModule(new string[] { "ShowUI" });
                Runspace rs = RunspaceFactory.CreateRunspace(iss);
                rs.ApartmentState = System.Threading.ApartmentState.STA;
                rs.ThreadOptions = PSThreadOptions.UseCurrentThread;
                rs.Open();
                Runspace.DefaultRunspace = rs;
                rs.SessionStateProxy.SetVariable("psIse", this.HostObject);
                rs.SessionStateProxy.SetVariable("window", System.Windows.Application.Current.MainWindow);
                System.Windows.Application.Current.MainWindow.Resources["Timers"] =
                    new System.Collections.Generic.Dictionary<string,System.Windows.Threading.DispatcherTimer>();
                System.Windows.Application.Current.MainWindow.Resources["TemporaryControls"] =
                    new System.Collections.Hashtable(StringComparer.InvariantCultureIgnoreCase);
                System.Windows.Application.Current.MainWindow.Resources["Scripts"] =
                    new System.Collections.Generic.Dictionary<string,ScriptBlock>();
 
 
                PowerShell initcmd = PowerShell.Create().AddScript(@"
`$Window.add_Closing({
            foreach (`$timer in `$this.Resources.Timers.Values) {
                if (-not `$timer) { continue }
                `$null = `$timer.Stop()
            }
            `$this |
                Get-ChildControl -PeekIntoNestedControl |
                Where-Object {
                    `$_.Resources.EventHandlers
                } |
                ForEach-Object {
                    `$object = `$_
                    `$handlerNames = @(`$_.Resources.EventHandlers.Keys)
                    foreach (`$handler in `$handlerNames){
                        `$object.""remove_`$(`$handler.Substring(3))"".Invoke(`$object.Resources.EventHandlers[`$handler])
                        `$null = `$object.Resources.EventHandlers.Remove(`$handler)
                    }
                    `$object.Resources.Remove(""EventHandlers"")
                }
        })
");
                initcmd.Runspace = rs;
                initcmd.Invoke();
            }
             
            PowerShell psCmd = PowerShell.Create().AddScript(@"
$($ScriptBlock.ToString().Replace('"','""'))
");
            psCmd.Runspace = Runspace.DefaultRunspace;
            try {
 
                FrameworkElement ui = psCmd.Invoke<FrameworkElement>()[0];
                 
                 
                Runspace.DefaultRunspace.SessionStateProxy.SetVariable("${DisplayName}_Icicle", ui);
 
 
                this.Content = ui;
                if (ui.GetValue(Control.WidthProperty) != null) {
                    this.Width = ui.Width;
                }
                if (ui.GetValue(Control.HeightProperty) != null) {
                    this.Height = ui.Height;
                }
                if (ui.GetValue(Control.MinWidthProperty) != null) {
                    this.MinWidth = ui.MinWidth;
                }
                if (ui.GetValue(Control.MinHeightProperty) != null) {
                    this.MinHeight = ui.MinHeight;
                }
                if (ui.GetValue(Control.MaxWidthProperty) != null) {
                    this.MaxWidth = ui.MaxWidth;
                }
                if (ui.GetValue(Control.MaxHeightProperty) != null) {
                    this.MaxHeight = ui.MaxHeight;
                }
            } catch {
            }
             
        }
                         
 
        public PSObject[] InvokeScript(string script, object parameters)
        {
            return (PSObject[])RunOnUIThread(
            new DispatcherOperationCallback(
            delegate
            {
                PowerShell psCmd = PowerShell.Create();
                Runspace.DefaultRunspace.SessionStateProxy.SetVariable("this", this);
                psCmd.Runspace = Runspace.DefaultRunspace;
                psCmd.AddScript(script);
                if (parameters is IDictionary)
                {
                    psCmd.AddParameters(parameters as IDictionary);
                }
                else
                {
                    if (parameters is IList)
                    {
                        psCmd.AddParameters(parameters as IList);
                    }
                }
                Collection<PSObject> results = psCmd.Invoke();
                if (psCmd.InvocationStateInfo.Reason != null)
                {
                    throw psCmd.InvocationStateInfo.Reason;
                }
                PSObject[] resultArray = new PSObject[results.Count + psCmd.Streams.Error.Count];
                int count = 0;
                if (psCmd.Streams.Error.Count > 0)
                {
                    foreach (ErrorRecord err in psCmd.Streams.Error)
                    {
                        resultArray[count++] = new PSObject(err);
                    }
                }
                foreach (PSObject r in results)
                {
                    resultArray[count++] = r;
                }
                return resultArray;
            }),
            false);
             
        }
 
        object RunOnUIThread(DispatcherOperationCallback dispatcherMethod, bool async)
        {
            if (Application.Current != null)
            {
                if (Application.Current.Dispatcher.Thread == Thread.CurrentThread)
                {
                    // This avoids dispatching to the UI thread if we are already in the UI thread.
                    // Without this runing a command like 1/0 was throwing due to nested dispatches.
                    return dispatcherMethod.Invoke(null);
                }
            }
 
            Exception e = null;
            object returnValue = null;
            SynchronizationContext sync = new DispatcherSynchronizationContext(this.Dispatcher);
            if (async) {
                sync.Post(
                    new SendOrPostCallback(delegate(object obj)
                    {
                        try
                        {
                            returnValue = dispatcherMethod.Invoke(obj);
                        }
                        catch (Exception uiException)
                        {
                            e = uiException;
                        }
                    }),
                    null);
 
            } else {
                sync.Send(
                    new SendOrPostCallback(delegate(object obj)
                    {
                        try
                        {
                            returnValue = dispatcherMethod.Invoke(obj);
                        }
                        catch (Exception uiException)
                        {
                            e = uiException;
                        }
                    }),
                    null);
 
            }
 
            if (e != null)
            {
                throw new System.Reflection.TargetInvocationException(e.Message, e);
            }
            return returnValue;
        }
    }
         
}
"@


$presentationFramework = [System.Windows.Window].Assembly.FullName
$presentationCore = [System.Windows.UIElement].Assembly.FullName
$windowsBase=[System.Windows.DependencyObject].Assembly.FullName
$gPowerShell=[Microsoft.PowerShell.Host.ISE.PowerShellTab].Assembly.FullName
if ('System.Xaml.XamlReader' -as [type]) {
    $systemXaml=[system.xaml.xamlreader].Assembly.FullName
} else {
    $systemXaml=[Windows.Markup.xamlreader].Assembly.FullName

}
$systemManagementAutomation=[psobject].Assembly.FullName
$newItem = $null
$t = add-type -TypeDefinition $addOnType -ReferencedAssemblies $systemManagementAutomation,$presentationFramework,$presentationCore,$windowsBase,$gPowerShell,$systemXaml -ignorewarnings -PassThru |
    Select-Object -First 1 

if ($addHorizontally -and $psVersionTable.PSVersion -ge '3.0') {
    $exists=  $psISE.CurrentPowerShellTab.HorizontalAddOnTools | Where-Object { $_.Name -eq "$displayName" } 
    if ($Exists -and $Force) {
        $null = $psISE.CurrentPowerShellTab.HorizontalAddOnTools.Remove($exists)
    }
    $newItem = $psISE.CurrentPowerShellTab.HorizontalAddOnTools.Add("$displayName",$t,$true)
    if (-not $DoNotShow) {
        $psISE.CurrentPowerShellTab.HorizontalAddOnToolsPaneOpened = $true
    }
} elseif ($addVertically -and $psVersionTable.PSVersion -ge '3.0') {
    $exists=  $psISE.CurrentPowerShellTab.VerticalAddOnTools | Where-Object { $_.Name -eq "$displayName" } 
    if ($Exists -and $Force) {
        $null = $psISE.CurrentPowerShellTab.VerticalAddOnTools.Remove($exists)
    }
    $newItem = $psISE.CurrentPowerShellTab.VerticalAddOnTools.Add("$displayName",$t,$true)
    if (-not $DoNotShow) {
        $psISE.CurrentPowerShellTab.VerticalAddOnToolsPaneOpened = $true
    }
    
} elseif ($addFloating) {
    if (-not $script:FloatingAddOns) {
        $script:FloatingAddOns = @{}
    }
    $sb = [ScriptBlock]::Create("`$this.Content= New-Object '$t'")

    
    $script:FloatingAddOns[$DisplayName] =     New-Window -Title $displayName -SizeToContent WidthAndHeight -On_Initialized $sb -AsJob
    $script:FloatingAddOns[$DisplayName]
} else {
    $t
}

if ($newItem) {
    $null = $newItem.Control.InvokeScript({$this.MainRunspace = $args | Select-Object -First 1 }, @([Runspace]::DefaultRunspace)) 
    $null = $newItem.Control.InvokeScript({$this.Resources.ShortcutKey = $args}, @($shortcutkey)) 
    $newItem
}

$iciclesMenu = $psise.CurrentPowerShellTab.AddOnsMenu.Submenus | Where-Object { $_.DisplayName -eq 'Icicles'}
if (-not $iciclesMenu) {
    $iciclesMenu = $psise.CurrentPowerShellTab.AddOnsMenu.Submenus.Add("Icicles", $null, $null) 
}

$icicleMenuItem = $iciclesMenu.submenus | 
    Where-Object { $_.DisplayName -eq $displayName } 
if ($icicleMenuItem) {
    $null = $iciclesMenu.submenus.Remove($icicleMenuItem)
}

$toggleAction = [ScriptBlock]::Create("Get-Icicle '`$displayName' | Show-Icicle")

if ($shortcutKey) {
    foreach ($sc in @($shortcutKey) + $null) {
        try {
            if (-not $sc) {
                $iciclesMenu.Add($displayName, $toggleAction, $null)
            } else {
                $iciclesMenu.Add($displayName, $toggleAction, $sc)

            }
        } catch {
            Write-Warning "Could not add $displayName with Shortcut Key $sc."
        }
    }
} else {
    $iciclesMenu.Submenus.Add($displayName, $toggleAction, $null)
}
            
    }
}