Search PowerShellers and other PowerShell-related sites

Sunday, May 3, 2009

What happened to a CustomMenu property?

If you'd like to customize your Windows PowerShell ISE be prepared for some breaking changes in Windows PowerShell ISE that comes with Windows 7 RC (May I call it Windows PowerShell ISE RC?). In Windows PowerShell ISE CTP3 $psISE, custom host variable, has following properties:

PS C:\> $psISE | gm -MemberType property


TypeName: System.Management.Automation.Host.PSGHost

Name MemberType Definition
---- ---------- ----------
CurrentOpenedFile Property System.Management.Automation.Host.OpenedFile CurrentOpenedFile {get;}
CurrentOpenedRunspace Property System.Management.Automation.Host.OpenedRunspace CurrentOpenedRunspace {get;}
CustomMenu Property System.Management.Automation.Host.PSMenuItem CustomMenu {get;}
OpenedRunspaces Property System.Management.Automation.Host.OpenedRunspaceCollection OpenedRunspaces {get;}
Options Property System.Management.Automation.Host.Options Options {get;}


Same command in Windows PowerShell ISE RC will give renamed type and properties:

TypeName: Microsoft.PowerShell.Host.ISE.ObjectModelRoot

Name MemberType Definition
---- ---------- ----------
CurrentFile Property Microsoft.PowerShell.Host.ISE.ISEFile CurrentFile {get;}
CurrentPowerShellTab Property Microsoft.PowerShell.Host.ISE.PowerShellTab CurrentPowerShellTab {get;}
Options Property Microsoft.PowerShell.Host.ISE.ISEOptions Options {get;}
PowerShellTabs Property Microsoft.PowerShell.Host.ISE.PowerShellTabCollection PowerShellTabs {get;}


Runspace is PowerShell Tab now, and Opened was unnecessary, but what happened to a CustomMenu property?

Let's see what CurrentPowerShellTab can offer:

PS C:\> $psISE.CurrentPowerShellTab | gm


TypeName: Microsoft.PowerShell.Host.ISE.PowerShellTab

Name MemberType Definition
---- ---------- ----------
... ... ...

AddOnsMenu Property Microsoft.PowerShell.Host.ISE.ISEMenuItem AddOnsMenu {get;}
... ... ...


It looks that we are on a right track. We used to run a command such as the following one to add customized menu item:

$psISE.CustomMenu.Submenus.Add("Run single line", {Invoke-CaretLine} , 'F7')


So, what we are looking for is a Submenus property. Let's hope that an AddOnsMenu has one. :)


PS C:\> $psise.CurrentPowerShellTab.AddOnsMenu | gm -MemberType property


TypeName: Microsoft.PowerShell.Host.ISE.ISEMenuItem

Name MemberType Definition
---- ---------- ----------

Action Property System.Management.Automation.ScriptBlock Action {get;}
DisplayName Property System.String DisplayName {get;}
Shortcut Property System.Windows.Input.KeyGesture Shortcut {get;}
Submenus Property System.Collections.Generic.IList`1[[Microsoft.PowerShell.Host.ISE.ISEMenuItem...


Bingo!

PS C:\> $psise.CurrentPowerShellTab.AddOnsMenu.Submenus | gm


TypeName: Microsoft.PowerShell.Host.ISE.ISEMenuItem

Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
Action Property System.Management.Automation.ScriptBlock Action {get;}
DisplayName Property System.String DisplayName {get;}
Shortcut Property System.Windows.Input.KeyGesture Shortcut {get;}
Submenus Property System.Collections.Generic.IList`1[[Microsoft.PowerShell.Host.ISE.ISEMenuItem...


What the fluff?! Where is an Add method?
As we have learnt in V1, when you miss some member use a psbase property:

PS C:\> $psISE.CurrentPowerShellTab.AddOnsMenu.Submenus.psbase | gm


TypeName: System.Management.Automation.PSMemberSet

Name MemberType Definition
---- ---------- ----------
CollectionChanged Event System.Collections.Specialized.NotifyCollectionChangedEventHandler CollectionChanged(System....
Add Method Microsoft.PowerShell.Host.ISE.ISEMenuItem Add(string displayName, scriptblock action,...
Clear Method System.Void Clear()
Contains Method bool Contains(Microsoft.PowerShell.Host.ISE.ISEMenuItem item)
CopyTo Method System.Void CopyTo(Microsoft.PowerShell.Host.ISE.ISEMenuItem[] array, int arrayIndex)
Equals Method bool Equals(System.Object obj)
GetEnumerator Method System.Collections.Generic.IEnumerator[Microsoft.PowerShell.Host.ISE.ISEMenuItem]
GetHashCode Method int GetHashCode()
GetType Method type GetType()
IndexOf Method int IndexOf(Microsoft.PowerShell.Host.ISE.ISEMenuItem item)
Insert Method System.Void Insert(int index, Microsoft.PowerShell.Host.ISE.ISEMenuItem item)
Remove Method bool Remove(Microsoft.PowerShell.Host.ISE.ISEMenuItem item)
RemoveAt Method System.Void RemoveAt(int index)
ToString Method string ToString()
Item ParameterizedProperty Microsoft.PowerShell.Host.ISE.ISEMenuItem Item(int index) {get;set;}
Count Property System.Int32 Count {get;}
IsReadOnly Property System.Boolean IsReadOnly {get;}


That's much better. :)

Now it's easy to add our first customized menu item:

$action = {$p = Read-Host "Enter parameter name";Get-Help * -parameter $p}
$psISE.CurrentPowerShellTab.AddOnsMenu.Submenus.Add("Find parameter",$action,'Ctrl+Shift+F3')


If we want to create a submenu, we need to omit an action:

$m = $psISE.CurrentPowerShellTab.AddOnsMenu.Submenus.Add("Execution Policy",$null,$null)


And then we can add the menu items:

$m.Submenus.Add("Get policy",{Get-ExecutionPolicy},'CTRL+Shift+J')
$m.Submenus.Add("Set policy",{Set-ExecutionPolicy RemoteSigned},'CTRL+Shift+K')


These changes are not persistent, and we will loose them when we close Windows PowerShell ISE. We can really extend our environment by putting the code into our Windows PowerShell ISE profile.

To summarize, Windows PowerShell ISE can have up to 8 PowerShell Tabs, and every tab can have its own set of customized menu items and submenus.

While we talk about changes in a new Windows PowerShell ISE, let's not forget that some shorcuts are changed as well (Run Selection is F8 now) and new toolbar is common for all three panes. The best new built-in menu item is the New Remote PowerShell Tab... which will start an interactive session with a remote computer.

Saturday, May 2, 2009

Upgrade Virtual PC 2007 before you virtualize Windows 7 RC

If you plan to install Windows 7 RC using Microsoft Virtual PC 2007, upgrade it to Virtual PC 2007 SP1 (6.0.192.0). Old version (6.0.156.0) will give you BSOD after you install Virtual Machine Additions (Error: Fs_Rec.sys - The driver mistakenly marked a part of its image pagable instead of nonpagable.)
Happily, System Restore works great. :)