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) } } } |