Learn How to Customize the Windows PowerShell Script Editor

Learn How to Customize the Windows PowerShell Script Editor

  • Comments 1
  • Likes

 

Summary: Learn how to customize the Windows PowerShell script editor by using readily available functions from the PowerShellPack.

 

Microsoft Scripting Guy Ed Wilson here. Even well-planned blogs often go astray. If you have been keeping up with our Weekend Scripter series, you know that today I am supposed to talk about adding a function to my Windows PowerShell ISE profile to retrieve stock quotes and weather forecasts. Unfortunately, one problem with web services is that if the web service is down, it is hard to troubleshoot your code. I have a really cool function I wrote, and it was working beautifully a few days ago, but then the web service I was using took a dirt nap. It has not came back up yet. In the meantime, James Brundage sent me a blog post about adding menu items to the Windows PowerShell ISE by using his IsePack. It actually makes a great follow-up to my series of articles about customizing the Windows PowerShell ISE.

James is the founder of Start-Automating (http://www.start-automating.com), a company dedicated to saving people time and money by helping them automate. Start-Automating offers Windows PowerShell training and custom Windows PowerShell and .NET Framework development. He is a former Microsoft employee from the Windows PowerShell team and is the author the PowerShellPack (http://code.msdn.microsoft.com/PowerShellPack), a collection of Windows PowerShell scripts that enable building user interfaces, interacting with RSS feeds, getting system information.

The floor is yours, James.

 

About a year ago, I released a module called IsePack, which has about 50 different add-on menu items for the Windows PowerShell Integrated Scripting Environment (ISE). IsePack has nested menus and shortcut keys for nearly everything. It also has some helper functions you can copy and reuse in your own projects. The IsePack is incorporated with the PowerShellPack.

Because IsePack has so many menus, it was important to find an easier way to structure the menus than writing each one out manually (as Ed Wilson discussed during an earlier Weekend Scripter article). In particular, I wanted to make sure my menus did the following things:

  • Provide the menu items in a convenient format.
  • Automatically replace a menu of the same name.
  • Allow for nested menus.
  • Alphabetize the menu items I had.
  • Allow for an easier way to add shortcut keys.

What I built was a nifty little function called Add-IseMenu. Go ahead, load IsePack and check it out

Import-Module IsePack

Get-Help Add-IseMenu -Full

Add-IseMenu takes the name of a menu and a hashtable that represents the menu, and optionally, a root level in which to put the menu.

It is a pretty well documented function, so you should not have any trouble using it on your own, but here is a quick example. This adds a menu called “Verb” with a nested menu for Get and Import. One of the items under Get, Get-Process, has a shortcut key (CTRL+ALT+SHIFT+P):

Add-IseMenu -Name "Verb" @{
   
Get = @{
                  
Process = { Get-Process } | Add-Member NoteProperty ShortcutKey "CTRL+ALT+SHIFT+P" -PassThru
                  
Service = { Get-Service }
                  
Hotfix = { Get-Hotfix } 
                
}
       
Import = @{
                  
Module = { Import-Module } 
                
}
    
}

As you can see, you can put a lot of menu structure in a fraction of the space as compared to writing out menu items the long way. Also, because the inputs for the menus are hashtables, it’s possible to build them up in script.

The previous posts in this series have helped customize the options screen. Let us see how much more we can do with Add-ISEMenu and a couple of helper functions.

$tokenColorMenu = @{}
$paneColorMenu = @{}
$outputColorMenu = @{}
function Edit-TokenColor($tokenType) {
   
$colorDialog = New-Object Windows.Forms.ColorDialog -Property @{
       
FullOpen = $true
       
Color = [Drawing.Color]::FromArgb($psise.Options.TokenColors["$tokenType"].R,
          
$psise.Options.TokenColors["$tokenType"].G,
          
$psise.Options.TokenColors["$tokenType"].B)
   
}
   
if ($colorDialog.ShowDialog() -eq "OK") {
          
$psise.Options.TokenColors["$tokenType"] = [Windows.Media.Color]::FromArgb(
          
255,

$colorDialog.Color.R,$colorDialog.Color.G,$colorDialog.Color.B)
   
}
}

function Edit-OptionColor($option) {
   
$colorDialog = New-Object Windows.Forms.ColorDialog -Property @{
       
FullOpen = $true
       
Color = [Drawing.Color]::FromArgb($psise.Options.$option.R,
           
$psise.Options.TokenColors.$option.G,
           
$psise.Options.TokenColors.$option.B)
   
}
   
if ($colorDialog.ShowDialog() -eq "OK") {
       
$psise.Options.$option = [Windows.Media.Color]::FromArgb(
           
255,

$colorDialog.Color.R,$colorDialog.Color.G,$colorDialog.Color.B)
   
}
}

foreach ($tokenType in $psise.Options.TokenColors.Keys) {
   
$menuAction = [ScriptBlock]::Create("Edit-TokenColor $tokenType")
   
$tokenColorMenu.$tokenType = $menuAction
}

$optionNames = $psise.Options | 
   
Get-Member *color* -MemberType Property |
   
Where-Object { $_.Definition -like "System.Windows.Media.Color*" }|
   
Select-Object -ExpandProperty Name

foreach ($optionName in $optionNames) {
   
$menuAction = [ScriptBlock]::Create("Edit-OptionColor $optionName")
   
if ($optionName -like "*pane*") {
       
$paneColorMenu.$optionName = $menuAction
   
} else {
       
$outputColorMenu.$optionName = $menuAction
   
}
}

Add-IseMenu -Name "Set-IseOptions" -Menu @{
    "Set-Font"
= {
       
$fontDialog = New-Object Windows.Forms.FontDialog
       
$fontDialog.Font = New-Object Drawing.Font $psise.Options.FontName, 
           
$psise.Options.FontSize
       
if ($fontDialog.ShowDialog() -eq "OK") {
           
$psise.Options.FontName = $fontDialog.Font.Name
           
$psise.Options.FontSize = $fontDialog.Font.Size
       
}
   
}
   
# Reset options is a script block with an extra property added... a shortcut
   
# key. If the shortcut key is found on any menu item in Add-IseMenu, then a shortcut
   
# key will be registered.
    "Reset-Options"
= {
       
$psise.Options.RestoreDefaults()
   
} | 
       
Add-Member NoteProperty ShortcutKey "CTRL + SHIFT + ALT + R" -PassThru
    "Set-Color"
= @{
        "Reset-TokenColor"
= { $psise.Options.RestoreDefaultTokenColors() }
        "Set-OutputColor"
= $outputColorMenu
        "Set-PaneColor"
= $paneColorMenu
        "Set-TokenColor"
= $tokenColorMenu
   
}
    "Set-HelpOptions"
= @{
        "Use-LocalHelp"
= {
           
$psise.Options.UseLocalHelp = $true
   
}
        "Use-OnlineHelp"
= {
           
$psise.Options.UseLocalHelp = $false
       
}
   
}
    "Set-SaveOptions"
= @{
        "Show-WarningForDuplicateFiles"
= {
           
$psise.Options.ShowWarningForDuplicateFiles = $true
       
}
        "Hide-WarningForDuplicateFiles"
= {
           
$psise.Options.ShowWarningForDuplicateFiles = $false
       
}
        "Show-WarningForSaveOnRun"
= {
           
$psise.Options.ShowWarningBeforeSavingOnRun = $true
       
}
        "Hide-WarningForSaveOnRun"
= {
           
$psise.Options.ShowWarningBeforeSavingOnRun = $false
       
}
   
}
    "Set-LayoutOptions"
= @{
        "Show-ToolBar"
= {
           
$psise.Options.ShowToolBar = $true
       
}
        "Hide-Toolbar"
= {
           
$psise.Options.ShowToolBar = $false
       
}
        "Set-ScriptPaneLocation"
= @{
            "Maximized"
= { $psise.Options.SelectedScriptPaneState = "Maximized" }
            "Top"
= { $psise.Options.SelectedScriptPaneState = "Top" }
            "Right"
= { $psise.Options.SelectedScriptPaneState = "Right" } 
       
}
   
}
}

In about 100 lines of code, we can make a menu to customize every part of the Windows PowerShell ISE. We can even make it so that we have color dialogs to change the colors of each setting.

Go ahead and give it a whirl. Click Add-OnMenu, click Set-IseOptions, click Set-TokenColor, and then click Comment. And change the color that the comments are.

You are welcome to copy and paste Add-IseMenu into your own projects, or simply check to see if the command is there in the top of your module. It’s a great way to quickly customize the Windows PowerShell ISE.

 

Thank you, James. One of the cool things about Windows PowerShell is that you always have options.

We would love for you to follow us on Twitter and Facebook. If you have any questions, send email to us at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

 

Ed Wilson and Craig Liebendorfer, Scripting Guys

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • Amazing

    Exemplary

    Inspiring

    Outstanding

    Useful

               Thanks.