PowerShell FontDialog GUI v2


I thought I would update my FontDialog script to demonstrate the selected font and style. I discovered that combining multiple font styles is not very intuitive. After selecting the font and it’s characteristics, sample text is displayed with those styles.


Here are the changes from the original script, excluding some minor rearrangement of the controls in the form.

There are five font styles. I set the style variables to $null, except for $setRegular which I assign the “Regular” FontStyle.

$setBold = $null
$setItalic = $null
$setRegular = [System.Drawing.FontStyle]::Regular
$setStrikeout = $null
$setUnderline = $null

After selecting a font and it’s styles, I check to see if a style has been selected (true) and if so set the FontStyle.

If ($font.Bold -eq "True") {
    $setBold = [System.Drawing.FontStyle]::Bold
If ($font.Italic -eq "True") {
    $setItalic = [System.Drawing.FontStyle]::Italic
If ($font.Strikeout -eq "True") {
    $setStrikeout = [System.Drawing.FontStyle]::Strikeout
If ($font.Underline -eq "True") {
    $setUnderline = [System.Drawing.FontStyle]::Underline

A single Font Style is set on a Font like –

$font = New-Object System.Drawing.Font("Comic Sans MS",17,[System.Drawing.FontStyle]::Regular)

For multiple FontStyles it is a bit trickier. FontStyle enumeration has a FlagsAttribute attribute consisting of a set of flags representing the styles. It is a a bitwise combination of the members values to set the attribute. You use -bor to join multiple FontStyle flag bits into the FlagsAttributes byte.

$newFont = New-Object System.Drawing.Font("Comic Sans MS",15,[System.Drawing.FontStyle]([System.Drawing.FontStyle]::Bold -bor [System.Drawing.FontStyle]::Underline))

Since any FontStyle other than Regular replaces Regular and you can -bor null value bits without affecting the byte, I used a single object to filter the styles. I first set Regular flag and then combine the other fours values, letting them fall out if not set. This allows none or any of the FontStyles to be used concurrently but will default to Regular if no addition styles are selected. The only property not set as from the Font Dialog selections is the size, which is fixed for display consistency.

$newFont = New-Object System.Drawing.Font($font.Name,17,[System.Drawing.FontStyle]($setRegular -bor $setBold -bor $setItalic -bor $setStrikeout -bor $setUnderline))

$titleLabel1.Font = $newFont
$titleLabel2.Font = $newFont

Download the complete script here – FontDialog2.ps1

PowerShell WinForms Menu

1 Comment

Most of the scripts I have written for this blog have custom interfaces for that script. But sometimes you need a Form laid out with the ‘Standard” Windows menu system. This script presents a WinForms Form layout with standard features including a pull-down menu supporting sub-menus, shortcut keys and icons. Also a toolbar with buttons representing menu options and a status bar on the bottom.
I first add the .Net assemblies and set EnableVisualStyles. This setting allows the Form to use the colors, fonts and other visual elements that form an operating system theme. All the controls used in the script will utilize the desktop theme.

# Install .Net Assemblies
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

# Enable Visual Styles

The below image is FormsMenu running on a desktop with a High Contrast theme so show how the WinForm elements follow the OS desktop theme when setting EnableVisualStyles.
The objects used in the main form are defined.

# Main Form .Net Objects
$mainForm         = New-Object System.Windows.Forms.Form
$menuMain         = New-Object System.Windows.Forms.MenuStrip
$menuFile         = New-Object System.Windows.Forms.ToolStripMenuItem
$menuView         = New-Object System.Windows.Forms.ToolStripMenuItem
$menuTools        = New-Object System.Windows.Forms.ToolStripMenuItem
$menuOpen         = New-Object System.Windows.Forms.ToolStripMenuItem
$menuSave         = New-Object System.Windows.Forms.ToolStripMenuItem
$menuSaveAs       = New-Object System.Windows.Forms.ToolStripMenuItem
$menuFullScr      = New-Object System.Windows.Forms.ToolStripMenuItem
$menuOptions      = New-Object System.Windows.Forms.ToolStripMenuItem
$menuOptions1     = New-Object System.Windows.Forms.ToolStripMenuItem
$menuOptions2     = New-Object System.Windows.Forms.ToolStripMenuItem
$menuExit         = New-Object System.Windows.Forms.ToolStripMenuItem
$menuHelp         = New-Object System.Windows.Forms.ToolStripMenuItem
$menuAbout        = New-Object System.Windows.Forms.ToolStripMenuItem
$mainToolStrip    = New-Object System.Windows.Forms.ToolStrip
$toolStripOpen    = New-Object System.Windows.Forms.ToolStripButton
$toolStripSave    = New-Object System.Windows.Forms.ToolStripButton
$toolStripSaveAs  = New-Object System.Windows.Forms.ToolStripButton
$toolStripFullScr = New-Object System.Windows.Forms.ToolStripButton
$toolStripAbout   = New-Object System.Windows.Forms.ToolStripButton
$toolStripExit    = New-Object System.Windows.Forms.ToolStripButton
$statusStrip      = New-Object System.Windows.Forms.StatusStrip
$statusLabel      = New-Object System.Windows.Forms.ToolStripStatusLabel

I use icons on the menu items, main form and the About form. These can acquired in a variety of ways, three of which I used here. First, for the icon on the main form I used the embedded icon from the PowerShell executable calling the System.Drawing.Icon.ExtractAssociatedIcon method.

$iconPS   = [Drawing.Icon]::ExtractAssociatedIcon((Get-Command powershell).Path)

There are a few icons that can be used in the SystemIcon Class. From this I used the Information icon on the About menu item.


The rest of the icons I pull out of shell32.dll, one of many Windows system files which contain icons. Without a direct call from PowerShell, I used the below code comes from the PowerShell Forum in the TechNet Script Center (http://social.technet.microsoft.com/Forums/scriptcenter/en-US/16444c7a-ad61-44a7-8c6f-b8d619381a27/using-icons-in-powershell-scripts?forum=winserverpowershell). After loading the assembly, you have a new Method to extract icons from DLL’s called IconExtractor.

# Create Icon Extractor Assembly
$code = @"
using System;
using System.Drawing;
using System.Runtime.InteropServices;

namespace System
	public class IconExtractor

	 public static Icon Extract(string file, int number, bool largeIcon)
	  IntPtr large;
	  IntPtr small;
	  ExtractIconEx(file, number, out large, out small, 1);
	   return Icon.FromHandle(largeIcon ? large : small);
	   return null;

	 [DllImport("Shell32.dll", EntryPoint = "ExtractIconExW", CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
	 private static extern int ExtractIconEx(string sFile, int iIndex, out IntPtr piLargeVersion, out IntPtr piSmallVersion, int amountIcons);

Add-Type -TypeDefinition $code -ReferencedAssemblies System.Drawing

I setup the Main Form defining the Menu and Icon and centering in the screen.

# Main Form
$mainForm.Height          = 400
$mainForm.Icon            = $iconPS
$mainForm.MainMenuStrip   = $menuMain
$mainForm.Width           = 800
$mainForm.StartPosition   = "CenterScreen"
$mainForm.Text            = " WinForms Menu Demo"

To build the Menu I first add the ToolStrip then the MenuStrip control to the Main Form. ToolsStrip is the base class for MenuStrip and StatusStrip, see the Control Architecture document. I then add the first (Top Level) ToolStripMenuItem, ‘File’, to the Main Menu Items list.

# Main ToolStrip

# Main Menu Bar

# Menu Options - File
$menuFile.Text = "File"

The Drop Down items are then added. The icon is added using the IconExtractor. The numeric is the icon number used to reference it. Shortcut Keys are defined and the text added. The MenuItem is then added as a DropDownItem under the ‘File’ Main menu item.

# Menu Options - File / Open
$menuOpen.Image        = [System.IconExtractor]::Extract("shell32.dll", 4, $true)
$menuOpen.ShortcutKeys = "Control, O"
$menuOpen.Text         = "Open"

# Menu Options - File / Save
$menuSave.Image        = [System.IconExtractor]::Extract("shell32.dll", 36, $true)
$menuSave.ShortcutKeys = "F2"
$menuSave.Text         = "Save"

# Menu Options - File / Save As
$menuSaveAs.Image        = [System.IconExtractor]::Extract("shell32.dll", 45, $true)
$menuSaveAs.ShortcutKeys = "Control, S"
$menuSaveAs.Text         = "Save As"

# Menu Options - File / Exit
$menuExit.Image        = [System.IconExtractor]::Extract("shell32.dll", 10, $true)
$menuExit.ShortcutKeys = "Control, X"
$menuExit.Text         = "Exit"

Nesting a Drop Down Menu Item under another is a matter of just adding it to the upper Drop Down Item, as under ‘Options’.

# Menu Options - Tools
$menuTools.Text      = "Tools"

# Menu Options - Tools / Options
$menuOptions.Image     = [System.IconExtractor]::Extract("shell32.dll", 21, $true)
$menuOptions.Text      = "Options"

# Menu Options - Tools / Options / Options 1
$menuOptions1.Image     = [System.IconExtractor]::Extract("shell32.dll", 33, $true)
$menuOptions1.Text      = "Options 1"

# Menu Options - Tools / Options / Options 2
$menuOptions2.Image     = [System.IconExtractor]::Extract("shell32.dll", 35, $true)
$menuOptions2.Text      = "Options 2"

The Buttons in the toolbar are made with a ToolStripButton. Each Button uses the icon from the Menu Items and calls the same Functions.

# ToolStripButton - Open
$toolStripOpen.ToolTipText  = "Open"
$toolStripOpen.Image = $menuOpen.Image

The Status bar is created by the StatusStrip Class control. The text is created by using a ToolStripStatusLabel Class control.

# Status Bar Label
$statusLabel.AutoSize  = $true
$statusLabel.Text      = "Ready"

Most of the Menu Items do nothing, however there are three options with working functions. The first two are “File Open” and “Save As”, which call OpenFileDialog and SaveFileDialog controls. You select what to look for, where to start and what to say. I set a variable with the filename when you make the selection.

function OpenFile {
    $statusLabel.Text = "Open File"
    $selectOpenForm = New-Object System.Windows.Forms.OpenFileDialog
    $selectOpenForm.Filter = "All Files (*.*)|*.*"
    $selectOpenForm.InitialDirectory = ".\"
    $selectOpenForm.Title = "Select a File to Open"
    $getKey = $selectOpenForm.ShowDialog()
    If ($getKey -eq "OK") {
        $inputFileName = $selectOpenForm.FileName
    $statusLabel.Text = "Ready"

function SaveAs {
    $statusLabel.Text = "Save As"
    $selectSaveAsForm = New-Object System.Windows.Forms.SaveFileDialog
    $selectSaveAsForm.Filter = "All Files (*.*)|*.*"
    $selectSaveAsForm.InitialDirectory = ".\"
    $selectSaveAsForm.Title = "Select a File to Save"
    $getKey = $selectSaveAsForm.ShowDialog()
    If ($getKey -eq "OK") {
        $outputFileName = $selectSaveAsForm.FileName
    $statusLabel.Text = "Ready"

The final working menu selection is “About”. A new Form is created containing the same PowerShell icon from the main form in a PictureBox as well as a comment.

function About {
    $statusLabel.Text = "About"
    # About Form Objects
    $aboutForm          = New-Object System.Windows.Forms.Form
    $aboutFormExit      = New-Object System.Windows.Forms.Button
    $aboutFormImage     = New-Object System.Windows.Forms.PictureBox
    $aboutFormNameLabel = New-Object System.Windows.Forms.Label
    $aboutFormText      = New-Object System.Windows.Forms.Label

    # About Form
    $aboutForm.AcceptButton  = $aboutFormExit
    $aboutForm.CancelButton  = $aboutFormExit
    $aboutForm.ClientSize    = "350, 110"
    $aboutForm.ControlBox    = $false
    $aboutForm.ShowInTaskBar = $false
    $aboutForm.StartPosition = "CenterParent"
    $aboutForm.Text          = "About FormsMenu.ps1"

    # About PictureBox
    $aboutFormImage.Image    = $iconPS.ToBitmap()
    $aboutFormImage.Location = "55, 15"
    $aboutFormImage.Size     = "32, 32"
    $aboutFormImage.SizeMode = "StretchImage"

    # About Name Label
    $aboutFormNameLabel.Font     = New-Object Drawing.Font("Microsoft Sans Serif", 9, [System.Drawing.FontStyle]::Bold)
    $aboutFormNameLabel.Location = "110, 20"
    $aboutFormNameLabel.Size     = "200, 18"
    $aboutFormNameLabel.Text     = "WinForms Menu Demo"

    # About Text Label
    $aboutFormText.Location = "100, 40"
    $aboutFormText.Size     = "300, 30"
    $aboutFormText.Text     = "          Wayne Lindimore `n`r AdminsCache.WordPress.com"

    # About Exit Button
    $aboutFormExit.Location = "135, 70"
    $aboutFormExit.Text     = "OK"

    $statusLabel.Text = "Ready"
} # End About

Download the complete script here – FormsMenu.ps1

PowerShell Color Selection with ColorDialog


You can allow for color selection in your PowerShell GUI with the System.Windows.Forms.ColorDialog. You can have access to select from millions of colors. The ColorDialog allows selection of 48 Basic Colors or expand the dialog and select from any custom color, depending on your system.


In a WinForms form I added Labels and TextBoxes for R,G,B,A and the Color Name.

Add-Type -AssemblyName System.Windows.Forms

# Main Form
$mainForm = New-Object System.Windows.Forms.Form
$mainForm.Font = "Comic Sans MS,10"
$mainForm.Text = " Color Dialog Demo"
$mainForm.ForeColor = "White"
$mainForm.BackColor = "DarkBlue"
$mainForm.Width = 450
$mainForm.Height = 330

# Red Label
$redLabel = New-Object System.Windows.Forms.Label
$redLabel.Location = "45,50"
$redLabel.Height = 22
$redLabel.Width = 100
$redLabel.Text = "Red"

# Red TextBox
$redTextBox = New-Object System.Windows.Forms.TextBox
$redTextBox.Location = "180,50"
$redTextBox.Size = "100,20"
$redTextBox.ForeColor = "MediumBlue"
$redTextBox.BackColor = "White"

I added a TextBox to display some sample text in a large font which I’ll change the color of to match the color selected.

# Color Demo TextBox
$colorDemoTextBox = New-Object System.Windows.Forms.TextBox
$colorDemoTextBox.Font = "Comic Sans MS,28"
$colorDemoTextBox.Location = "130,200"
$colorDemoTextBox.Size = "200,200"
$colorDemoTextBox.ForeColor = "MediumBlue"
$colorDemoTextBox.BackColor = "White"
$colorDemoTextBox.Text = " Color 1234"

When you click the “Pick Color” button the PickColor function is called. I define the ColorDialog object, set it to allow the dialog to be expanded for custom colors and display it. I collect the R,G,B,and A values as well as the Color Name. The Alpha (A) value represents transparency. The Color Name us usually the concatenated hex value of the combined ARGB values, but for the approximately 150 Named Colors the function returns the colors name. See the .Net Color Structure for those Color Names. I convert the returned hex value to Int32 to feed into the ForeColor of the sample TextBox, but the Named Colors will fail so I capture the error and use the Colors Name for those values. The TextBox ForeColor will accept either value.

# Lookup Button
$lookupButton = New-Object System.Windows.Forms.Button
$lookupButton.Location = "300,20"
$lookupButton.Size = "85,28"
$lookupButton.ForeColor = "Green"
$lookupButton.BackColor = "White"
$lookupButton.Text = "Pick Color"

function PickColor {
    $colorDialog = new-object System.Windows.Forms.ColorDialog
    $colorDialog.AllowFullOpen = $true
    $alphaTextBox.Text = $colordialog.color.A
    $redTextBox.Text = $colordialog.color.R
    $greenTextBox.Text = $colordialog.color.G
    $blueTextBox.Text = $colordialog.color.B
    $colorNameTextBox.Text = $colorDialog.Color.Name
    $colorDemoTextBox.ForeColor = [Convert]::ToInt32($colorDialog.Color.Name, 16)
    If($error.count -gt 0) {
        $colorDemoTextBox.ForeColor = $colorDialog.Color.Name

Note – In order to pick up a custom colors value, it needs to be added to the Custom Colors list in the ColorDialog. See the ColorDialog image above as an example.



Two Calendar Controls for PowerShell

Leave a comment

Often you need to collect a date as a parameter for a script. There are several ways to display a GUI calendar to select the date from. I made a demo script for two of the calendar controls. Both are part of the System.Windows.Forms namespace. The MonthCalendar Class displays in a monthly view. You can move forward or back through the months or click into it and change to a less and less granular view. The DateTimePicker Class defaults to a single line display which can open into the monthly view.

In a simple WinForms form –

Add-Type -AssemblyName System.Windows.Forms
# Main Form
$mainForm = New-Object System.Windows.Forms.Form
$mainForm.Font = "Comic Sans MS,8.25"
$mainForm.Text = " Calendar Controls Demo"
$mainForm.ForeColor = "White"
$mainForm.BackColor = "DarkOliveGreen"
$mainForm.Width = 400
$mainForm.Height = 30

I added the MonthCalendar control. I set several properties including minimum and maximum dates displayed, how many dates can be concurrently selected, which day of the week in the first column and several others. This control has a lot of properties to manage it’s presentation.

# MonthCalendar
$monthCal = New-Object System.Windows.Forms.MonthCalendar
$monthCal.Location = "8,24"
$monthCal.MinDate = New-Object System.DateTime(2013, 1, 1)
$monthCal.MinDate = "01/01/2012"    # Minimum Date Dispalyed
$monthCal.MaxDate = "12/31/2013"    # Maximum Date Dispalyed
$monthCal.MaxSelectionCount = 1     # Max number of days that can be selected
$monthCal.ShowToday = $false        # Show the Today Banner at bottom
$monthCal.ShowTodayCircle = $true   # Circle Todays Date
$monthCal.FirstDayOfWeek = "Sunday" # Which Day of the Week in the First Column
$monthCal.ScrollChange = 1          # Move number of months at a time with arrows
$monthCal.ShowWeekNumbers = $false  # Show week numbers to the left of each week

I then added the DateTimePicker control. I set the min and max dates to match the MonthCalendar controls limitations. Not all of the MonthCalendar Properties are available with the DateTimePicker.

# DateTimePicker
$datePicker = New-Object System.Windows.Forms.DateTimePicker
$datePicker.Location = "18,220"
$datePicker.MinDate = "01/01/2013" # Minimum Date Dispalyed
$datePicker.MaxDate = "12/31/2013" # Maximum Date Dispalyed

The Select button will add the selected date to the TextBox for that calendar on the click event. The MonthCalendar and DateTimePicker controls work slightly differently. With MonthCalendar you can select a date range so to get a single date you use the SelectionStart property. While DateTimePicker supports only a single date and so you use it’s Value property.

# Select Button 1
$dateTimePickerButton = New-Object System.Windows.Forms.Button
$dateTimePickerButton.Location = "270,150"
$dateTimePickerButton.Size = "75,23"
$dateTimePickerButton.ForeColor = "DarkBlue"
$dateTimePickerButton.BackColor = "White"
$dateTimePickerButton.Text = "<<<-- Select"
    $textBox.Text = $monthCal.SelectionStart
    $textBox.Text = $textBox.Text.Substring(0,10)


# Select Button 2
$monthlyCalendarButton = New-Object System.Windows.Forms.Button
$monthlyCalendarButton.Location = "270,220"
$monthlyCalendarButton.Size = "75,23"
$monthlyCalendarButton.ForeColor = "DarkBlue"
$monthlyCalendarButton.BackColor = "White"
$monthlyCalendarButton.Text = "<<<-- Select"
    $textBox.Text = $datePicker.Value
    $textBox.Text = $textBox.Text.Substring(0,10)



PowerShell FontDialog GUI

Leave a comment

Note – I have updated this script, please see FontDialog2.ps1 for the changes which display the selected Font and Style(s).


On occasion you may need to interactively select a particular font from the installed fonts list. The System.Windows.Forms.FontDialog class offers a nice selection dialog. You can select the font family, size, bold, italic, script (character set) and effects while showing a font sample.


I put together a demo script to show the font properties you can gather while selecting a font. Just click Select Font and define your needs, click OK, and the results are displayed. You can also gather the current font info by clicking Select Font and then canceling the FontDialog.

I defined a WinForms form and the various Labels and TextBoxes.

Add-Type -AssemblyName System.Windows.Forms

# Main Form
$mainForm = New-Object System.Windows.Forms.Form
$mainForm.Font = "Comic Sans MS,8.25"
$mainForm.Text = " FontDialog Demo"
$mainForm.ForeColor = "White"
$mainForm.BackColor = "DarkSlateBlue"
$mainForm.Width = 400
$mainForm.Height = 500

# Labels
$fontNameLabel = New-Object System.Windows.Forms.Label
$fontNameLabel.Font = "Comic Sans MS,10"
$fontNameLabel.Location = "20,20"
$fontNameLabel.Size = "120,20"
$fontNameLabel.Text = "Font Family"

# TextBoxes
$fontNameTextBox = New-Object System.Windows.Forms.TextBox
$fontNameTextBox.Location = "140,20"
$fontNameTextBox.Size = "200,20"
$fontNameTextBox.Text = ""

When you click the “Select Font” button I display the FontDialog window. After the FontDialog control completes, I gather all the returned properties from the $fontDialog.font array and display those values in the TextBoxes.

# Select Button
$fontSelectButton = New-Object System.Windows.Forms.Button
$fontSelectButton.ForeColor = "DarkSlateBlue"
$fontSelectButton.BackColor = "White"
$fontSelectButton.Location = "20, 400"
$fontSelectButton.Size = "75, 23"
$fontSelectButton.Text = "Select Font"
    $fontDialog = New-Object System.Windows.Forms.FontDialog
    [void] $fontDialog.ShowDialog()
    $font = $fontDialog.Font
    $fontNameTextBox.Text = $font.Name
    $fontSizeTextBox.Text = $font.Size
    $fontHeightTextBox.Text = $font.Height
    $fontUnitTextBox.Text = $font.Unit
    $fontBoldTextBox.Text = $font.Bold
    $fontItalicTextBox.Text = $font.Italic
    $fontStyleTextBox.Text = $font.Style
    $fontStrikeoutTextBox.Text = $font.Strikeout
    $fontUnderlineTextBox.Text = $font.Underline
    $fontIsSystemFontTextBox.Text = $font.IsSystemFont
    $fontGdiCharSetTextBox.Text = $font.GDICharSet
    $fontGdiVerticalFontTextBox.Text = $font.GDIVerticalFont

I added the Exit Button and display the form.

# Exit Button
$exitButton = New-Object System.Windows.Forms.Button
$exitButton.Location = "20,430"
$exitButton.Size = "75,23"
$exitButton.ForeColor = "Red"
$exitButton.BackColor = "White"
$exitButton.Text = "Exit"

[void] $mainForm.ShowDialog()



NotifyIcon Monitors CapsLock

Leave a comment

One of the most interesting WinForms classes is the NotifyIcon. With it your can create an icon in the System Tray area of the TaskBar. Combined with a Timer class object to countdown and raise events you can monitor and alert. The following PowerShell script monitors for a CapsLock change and alerts with a balloon from the system tray icon and a voice notification. At any time you can mouse over the icon for the current status. The icon also changes according to the CapsLock status with an up or down arrow for a visual reference.

First I setup the main form. It has no properties and is then hidden. I call a function to get the path from where the script is executing so I can find the icons.

function Get-ScriptDirectory { 
    $Invocation = (Get-Variable MyInvocation -Scope 1).Value
    $global:callPath = Split-Path $Invocation.MyCommand.Path
} # End Function Get-ScriptDirectory

# Main Form and Setup
$mainForm = New-Object System.Windows.Forms.form
$global:lastCapsLock = [System.Console]::CapsLock
$global:callPath = “”
# Hide Main Form
$mainForm.ShowInTaskbar = $false
$mainForm.WindowState = “minimized”

Next I added a Timer object. It will count down a predefined time and then process an event, calling the CapsLock status change function. The interval is in milliseconds. The function call in add_Tick is required to be in brackets.

# Timer Object
$timer = New-Object System.Windows.Forms.Timer
$timer.Interval = 2000

I then define the NotifyIcon and make it visible. Within the NotifyIcon I define a ContextMenu which is visible on a right-click of the icon. I add a MenuItem to it for the Exit option. Lastly I define a click event action to clean up and exit the script.

# NotifyIcon Objects
$notifyIcon= New-Object System.Windows.Forms.NotifyIcon
$contextMenu = New-Object System.Windows.Forms.ContextMenu
$notifyIcon.ContextMenu = $contextMenu
$notifyIcon.Visible = $true
$menuItem1 = New-Object System.Windows.Forms.MenuItem -ArgumentList “Exit”

# Add Exit MenuItem
     $notifyIcon.Visible = $False

I do an initial load of the values the NotifyIcon will use. I get the current CapsLock status and load up the correct text and icon.

# Inital Load
$capsLock = [System.Console]::CapsLock
if ($capsLock -eq $false) {
     $notifyIcon.Icon = $global:callPath + “\down.ico”
     $notifyIcon.Text = “CapsLock is Off”
if ($capsLock -eq $true) {
     $notifyIcon.Icon = $global:callPath + “\up.ico”
     $notifyIcon.Text = “CapsLock is On”

Next I setup the function checking for a CapsLock status change and popping up the alerts. I check the CapsLock status and compare it to a saved value from the previous check. If change I go to the appropriate routine and set the icon and text. I then set the balloons title, text, duration and icon. The icon can be one of a few standardized ToolTip icons like – info, warning, or error. I then set the text to be spoken and call the VoiceNotifcation function.

Function CapsLockCheck {
     $capsLock = [System.Console]::CapsLock
     if ($capsLock -eq $false) {
         if ($capsLock -ne $global:lastCapsLock) {
            $notifyIcon.Icon = $global:callPath + “\down.ico”
            $notifyIcon.Text = “CapsLock is Off”
            $notifyIcon.BalloonTipText = “CapsLock is Off”
            $notifyIcon.BalloonTipTitle = “CapsLock has Changed”
            $notifyIcon.BalloonTipIcon = “Info”
            $spokenText = “Caps Lock is Off”
            $global:lastCapsLock = $capsLock
     if ($capsLock -eq $true) {
         if ($capsLock -ne $global:lastCapsLock) {
            $notifyIcon.Icon = $global:callPath + “\up.ico”
            $notifyIcon.Text = “CapsLock is On”
            $notifyIcon.BalloonTipText = “CapsLock is On”
            $notifyIcon.BalloonTipTitle = “CapsLock has Changed”
            $notifyIcon.BalloonTipIcon = “Info”
            $spokenText = “Caps Lock is On”
            $global:lastCapsLock = $capsLock
} # End Function CapsLockCheck

The voice notification process just takes the passed text, and using the text to speech class, speaks it.

Function VoiceNotification {
     $Voice = New-Object System.Speech.Synthesis.SpeechSynthesizer
     $voice.rate = -1
     $voice.volume = 100
     [void] $voice.Speak($spokenText)
} # End Function VoiceNotification

Finally I start the NotifyIcon running using the WinForms Application class Run method.


Included in the zip file is also a command file to facilitate executing the script. It will start the script with a hidden PowerShell command window. There is also the two icon files. All the files should be in the same folder to run properly.

powershell.exe -windowstyle hidden -nologo -command .\CapsLockMonitor.ps1



FYI – In the next blog I encode and embed the icons directly into the script file.

Open Web Browser in PowerShell GUI

Leave a comment

I have been thinking about writing a script where I wanted to open some browsers within the interface. I thought I’d use the WinForms WebBrowser class. I put together a real simple script just to see how the control worked. The script does nothing except select between a couple different websites, but it does show one way the control could be used.

In a basic WinForms window setup I added the WebBrowser control configuring location, size and the URL. I also enabled the context menu (right click menu). That is the default for this property but since I am changing it in other WebBrowser controls I like to be explicit in each.

Add-Type -AssemblyName System.Windows.Forms
$URL1 = “http://www.wikipedia.com
$URL2 = “https://adminscache.wordpress.com
$URL3 = “http://www.microsoft.com

# WinForm Setup
$mainForm = New-Object System.Windows.Forms.Form
$mainForm.Font = “Comic Sans MS,9″
$mainForm.ForeColor = [System.Drawing.Color]::White
$mainForm.BackColor = [System.Drawing.Color]::DarkSlateBlue
$mainForm.Text = ” System.Windows.Forms.WebBrowser Class”
$mainForm.Width = 960
$mainForm.Height = 700

# Main Browser
$webBrowser1 = New-Object System.Windows.Forms.WebBrowser
$webBrowser1.IsWebBrowserContextMenuEnabled = $true
$webBrowser1.URL = $URL1
$webBrowser1.Width = 600
$webBrowser1.Height = 600
$webBrowser1.Location = “50, 25”

The selection of websites is done by clicking a CheckBox next to a small window of the website. The selection browsers are setup like the main browser except they are smaller and I have disabled the context menu on them.

# First Selectable Browser
$webBrowser2 = New-Object System.Windows.Forms.WebBrowser
$webBrowser2.IsWebBrowserContextMenuEnabled = $false
$webBrowser2.URL = $URL1
$webBrowser2.Width = 200
$webBrowser2.Height = 150
$webBrowser2.Location = “700, 50”

There is a CheckBox next to each selection browser. I check the first CheckBox and use it’s URL in the initial form load. I clear any checked boxes from the previous selection for a new URL .

# First Select Checkbox
$selectCheckbox1 = New-Object System.Windows.Forms.Checkbox
$selectCheckbox1.Location = “910,120”
$selectCheckbox1.Checked = $true
     $webBrowser1.URL = $URL1
     $selectCheckbox2.Checked = $false
     $selectCheckbox3.Checked = $false



%d bloggers like this: