Using the AddOnsMenu property in the PowerShell ISE

Perhaps the greatest feature of the PowerShell ISE is that it is extensible. In my last few articles on the PowerShell ISE I’ve been introducing you to the PSISE object model. The next step is to integrate some of these commands and functions directly into the ISE. We can do this by adding commands directly to the ISE menu.

Adding a Menu Item to the PowerShell ISE

The PowerShell ISE has an Add-Ons menu, which I’ve highlighted in the figure below.

The PowerShell ISE Adds On menu. (Image Credit: Jeff Hicks)
The PowerShell ISE Adds On menu. (Image Credit: Jeff Hicks)

Microsoft, members of the PowerShell community and you, can add items to this menu using the PSISE object model. Each PowerShell tab has an AddOnsMenu property.
The PowerShell AddOnsMenu property. (Image Credit: Jeff Hicks)
The PowerShell AddOnsMenu property. (Image Credit: Jeff Hicks)

This gets a little tricky because you don’t add an item here, but rather to the Submenus property using the Add() method. The syntax looks like this:

$psise.CurrentPowerShellTab.AddOnsMenu.Submenus.Add(,{ },)

You have to specify something for all three values, although you really only need the first two. If you don’t want to include a keyboard shortcut, such as Ctrl+Alt+7, you can use $Null. In way of demonstration, I’ll add a link to Notepad with a keyboard shortcut.

$psise.CurrentPowerShellTab.AddOnsMenu.Submenus.Add("Open _Notepad",{Notepad.exe},"Ctrl+Alt+N")

In the ISE, I can use the menu or the keyboard shortcut to launch Notepad. Remember that your command must be a script block, so don’t forget the {}.

The Open Notepad option has now been added to the PowerShell ISE menu. (Image Credit: Jeff Hicks)
The Open Notepad option has now been added to the PowerShell ISE menu. (Image Credit: Jeff Hicks)

If you make a mistake, then the best thing to do is to exit and restart the PowerShell ISE. In fact, this should tell you that this change only lasts for as long as your PowerShell session is open. You can put the command in your ISE profile script to make the change persistent, however. With that said, I usually pipe the command to Out-Null to suppress the pipeline output since I don’t really need to see it.

 $psise.CurrentPowerShellTab.AddOnsMenu.Submenus.Add("Open _Notepad",{Notepad.exe},"Ctrl+Alt+N") | Out-Null

But let’s integrate the PSISE object model. How about an add-on to open the current file in Notepad? First, test your command in the ISE.

 PS C:\scripts> &{Notepad $psise.CurrentFile.FullPath}

I’m testing inside a scriptblock since that is what I’ll eventually be using. Here’s my final code:

 $action = {if ($psise.CurrentFile.IsSaved) {
 Notepad $psise.CurrentFile.FullPath
 }
 else {
 Write-Warning "$($psise.CurrentFile.FullPath) has not been saved"
 }
 }
$psise.CurrentPowerShellTab.AddOnsMenu.Submenus.Add("Open Current File in Notepad",$Action,"Ctrl+Alt+O") | Out-Null

I added some logic to the scriptblock so that only saved files are opened in Notepad. Otherwise a warning will be written to the command pane.

Adding additional shortcuts to the Add-ons menu in the PowerShell ISE. (Image Credit: Jeff Hicks)
Adding additional shortcuts to the Add-ons menu in the PowerShell ISE. (Image Credit: Jeff Hicks)

You could add as many shortcuts as you need to this menu.

Adding a Sub-Menu to the PowerShell ISE

I think there’s also a better option to create your own submenu and add items there. You accomplish this by adding a shortcut without scriptblock and shortcut.

$MyMenu = $psise.CurrentPowerShellTab.AddOnsMenu.Submenus.Add("MyTools",$null,$null)

Prepping the MyTools option to include a submenu item. (Image Credit: Jeff Hicks)
Prepping the MyTools option to include a submenu item. (Image Credit: Jeff Hicks)

I saved the result to a variable. $MyMenu is an ISEMenuItem object that has its own Submenus property, which means I can add an item to it like this:

$MyMenu.Submenus.Add(
 "Save all unsaved files",
 {$psise.CurrentPowerShellTab.Files.Where({-Not $_.isSaved -AND -Not $_.IsUntitled}).Foreach({$_.save()})},
 "Ctrl+Alt+S") | Out-Null

Under the MyTools menu I now have a new command.

Example of submenu option in the PowerShell ISE. (Image Credit: Jeff Hicks)
Example of submenu option in the PowerShell ISE. (Image Credit: Jeff Hicks)

Now I can work in the ISE and keeping my hands on the keyboard, periodically hit Ctrl+Alt+S to save all my unsaved work.
The action can be as complicated as you need it to be. If you recall a few articles ago, I demonstrated using shortcut keys to cycle through open files. However, there is not a provision for cycling through PowerShell tabs. However, it is possible to do that with the PSISE object model, where I wrote a function to do just that:

 Function Get-NextISETab {
 [cmdletbinding()]
 Param()
$iseTabs = $psISE.PowerShellTabs
#get current tab
for ($i=0; $i -le $iseTabs.count-1; $i++) {
Write-Verbose $iseTabs[$i].Displayname
if ($iseTabs[$i].Displayname -eq $psISE.CurrentPowerShellTab.DisplayName) {
$current = $i
}
#check if the next index number if valid
if ($current++ -ge $iseTabs.count-1) {
$next = 0
}
else {
$next = $current++
$nextTab = $iseTabs[$next
$iseTabs.SelectedPowerShellTab = $NextTa
}

In order for this to work this function needs to be in my ISE profile script so every PowerShell tab would know about it. But I don’t want to have to take my hands off the keyboard, so I’ll add this to my menu.

$psise.CurrentPowerShellTab.AddOnsMenu.Submenus.Add("Switch next tab",{Get-NextISETab},"Ctrl+ALT+T") | out-null

Adding the Switch next tab option to the PowerShell ISE menu. (Image Credit: Jeff Hicks)
Adding the Switch next tab option to the PowerShell ISE menu. (Image Credit: Jeff Hicks)

I added it to the main add-ons menu. But it could have gone in MyTools as well. When using functions make sure the function is defined before you create the menu item.

With a little work, you can turn the PowerShell ISE into a tool that you control and that allows you to get more done with less effort. It might even be a little fun. If you are interested, you can download my Get-NextISETab function as a text file.
If you want to catch up on my article series about the PowerShell ISE and the ISE object model, here are the rest of the articles in the series: