Few years back, I had started wrapping my PowerShell scripts with some sort of GUI built using Windows Forms (used Primal Forms CE mostly). Things went fine for a while but then I stumbled across awesome posts by MVP Boe Prox on using WPF with PowerShell to do the same. (check Resources section)
Well I have been using this technique for a while to see various verbose messages being generated by my backend PowerShell functions.
I had been procrastinating the idea of playing with WPF for a while but then had a great discussion with MVP Chendrayan (Chen) and got inspired to do it.
One can use Visual Studio (Express Edition - which is free) to design the UI and then consume the XAML in PowerShell script...Isn't that Cool ! See resources section for links on that.
Often when we write the Code to present a nice UI to the end user there is a PowerShell console running in the background. In this post I would like to share a trick to hide/show the background console window. This trick works with both Winforms and XAML.
Note - PowerGUI & Visual Studio Express are absolutely FREE !
Note - PowerGUI & Visual Studio Express are absolutely FREE !
For the demo of this post I have a GUIdemo.ps1 script with below contents :
001
002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 |
[xml]$xaml= @"
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Name="HideWindow" Title="Initial Window" WindowStartupLocation = "CenterScreen" Width = "335" Height = "208" ShowInTaskbar = "True" Background = "lightgray"> <Grid Height="159" Name="grid1" Width="314"> <TextBox Height="46" HorizontalAlignment="Left" Margin="44,30,0,0" Name="textBox" VerticalAlignment="Top" Width="199" /> <CheckBox Content="Show PS Windpw" Height="52" HorizontalAlignment="Left" Margin="34,95,0,0" Name="checkBox" VerticalAlignment="Top" Width="226" FontSize="15" /> </Grid> </Window> "@ Add-Type -AssemblyName PresentationFramework $reader=(New-Object System.Xml.XmlNodeReader $xaml) $Window=[Windows.Markup.XamlReader]::Load( $reader ) #Tie the Controls $CheckBox = $Window.FindName('checkBox') $textbox = $Window.FindName('textBox') $CheckBox.Add_Checked({$textbox.text = "Showing PS Window"; Show-Console}) $CheckBox.Add_UnChecked({$textbox.text = "Hiding PS Window"; Hide-Console}) $Window.ShowDialog() |
Save the above contents in a file and right click on it select "Run with PowerShell".
This will open up a PowerShell console window and our simple UI , right now if you check the checkbox it writes to the textbox but later on we will be able to toggle the background PowerShell Window on and off.
One of the simplest ways to hide this window as I have shown in one of my earlier post is by using PowerGUI to wrap it as an exe
Open the Script in PowerGUI Script Editor and then go to Tools > Compile Script
This will open up another window where you can select to not show the PowerShell console.
But this option will either permanently hide the window or show it. What if I wanted to give the end users an option to toggle the background PowerShell window on and off. You would ask what purpose would it serve ?
Well I have been using this technique for a while to see various verbose messages being generated by my backend PowerShell functions.
In addition to that we can use write-host to highlight few key things in the console (Write-Host is perfect candidate here cause we just want to show stuff on the host).
So let's add the code which will provide the functionality to toggle the background PowerShell console.
Re-used the code provided at PowerShell.cz to P/Invoke.
001
002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 |
#Function Definitions # Credits to - http://powershell.cz/2013/04/04/hide-and-show-console-window-from-gui/ Add-Type -Name Window -Namespace Console -MemberDefinition ' [DllImport("Kernel32.dll")] public static extern IntPtr GetConsoleWindow(); [DllImport("user32.dll")] public static extern bool ShowWindow(IntPtr hWnd, Int32 nCmdShow); ' function Show-Console { $consolePtr = [Console.Window]::GetConsoleWindow() [Console.Window]::ShowWindow($consolePtr, 5) } function Hide-Console { $consolePtr = [Console.Window]::GetConsoleWindow() [Console.Window]::ShowWindow($consolePtr, 0) } |
Now time to bind the functions above to the checkbox control and use few Write-Host statements in the code to make my case.
001
002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 |
[xml]$xaml= @"
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Name="HideWindow" Title="Initial Window" WindowStartupLocation = "CenterScreen" Width = "335" Height = "208" ShowInTaskbar = "True" Background = "lightgray"> <Grid Height="159" Name="grid1" Width="314"> <TextBox Height="46" HorizontalAlignment="Left" Margin="44,30,0,0" Name="textBox" VerticalAlignment="Top" Width="199" /> <CheckBox Content="Show PS Windpw" Height="52" HorizontalAlignment="Left" Margin="34,95,0,0" Name="checkBox" VerticalAlignment="Top" Width="226" FontSize="15" /> </Grid> </Window> "@ Add-Type -AssemblyName PresentationFramework $reader=(New-Object System.Xml.XmlNodeReader $xaml) $Window=[Windows.Markup.XamlReader]::Load( $reader ) Write-Host -ForegroundColor Cyan -Object "Welcome to the Hide/Show Console Demo" Write-Host -ForegroundColor Green -Object "Demo by DexterPOSH" #Tie the Controls $CheckBox = $Window.FindName('checkBox') $textbox = $Window.FindName('textBox') #Function Definitions # Credits to - http://powershell.cz/2013/04/04/hide-and-show-console-window-from-gui/ Add-Type -Name Window -Namespace Console -MemberDefinition ' [DllImport("Kernel32.dll")] public static extern IntPtr GetConsoleWindow(); [DllImport("user32.dll")] public static extern bool ShowWindow(IntPtr hWnd, Int32 nCmdShow); ' function Show-Console { $consolePtr = [Console.Window]::GetConsoleWindow() [Console.Window]::ShowWindow($consolePtr, 5) } function Hide-Console { $consolePtr = [Console.Window]::GetConsoleWindow() [Console.Window]::ShowWindow($consolePtr, 0) } Hide-Console # hide the console at start #Events Write-host -ForegroundColor Red "Warning : There is an issue" $CheckBox.Add_Checked({$textbox.text = "Showing PS Window"; Show-Console}) $CheckBox.Add_UnChecked({$textbox.text = "Hiding PS Window"; Hide-Console}) $Window.ShowDialog() | Out-Null |
Now copy the above code in PowerGUI and wrap it as an exe. Once done open the exe . Below is an animated GIF showing it in action (at the end it's a bit blurry cause of low FPS capture in gifcam).
Resources :
MVP Boe Prox's post on WPF
http://learn-powershell.net/category/wpf/
Hide and Show console from GUI
http://powershell.cz/2013/04/04/hide-and-show-console-window-from-gui/
MVP Boe Prox's post on WPF
http://learn-powershell.net/category/wpf/
Integrating XAML into PowerShell
http://blogs.technet.com/b/platformspfe/archive/2014/01/20/introduction-to-xaml.aspxHide and Show console from GUI
http://powershell.cz/2013/04/04/hide-and-show-console-window-from-gui/