├── .gitignore
├── PSScriptMenuGui
├── examples
│ ├── example_text_file.txt
│ ├── example_target.cmd
│ ├── pwsh7.ico
│ ├── example_target.ps1
│ ├── PSScriptMenuGui.ps1
│ ├── PSScriptMenuGui_all_options.ps1
│ └── example_data.csv
├── xaml
│ ├── end.xaml
│ ├── heading.xaml
│ ├── item.xaml
│ └── start.xaml
├── PSScriptMenuGui.psm1
├── PSScriptMenuGui.psd1
├── public
│ └── functions.ps1
└── private
│ └── functions.ps1
├── demo.gif
├── demo.mp4
├── excel.png
├── LICENSE
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | .vscode/
2 |
--------------------------------------------------------------------------------
/PSScriptMenuGui/examples/example_text_file.txt:
--------------------------------------------------------------------------------
1 | hello world
--------------------------------------------------------------------------------
/PSScriptMenuGui/xaml/end.xaml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dan-osull/PowerShell-Script-Menu-Gui/HEAD/demo.gif
--------------------------------------------------------------------------------
/demo.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dan-osull/PowerShell-Script-Menu-Gui/HEAD/demo.mp4
--------------------------------------------------------------------------------
/excel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dan-osull/PowerShell-Script-Menu-Gui/HEAD/excel.png
--------------------------------------------------------------------------------
/PSScriptMenuGui/examples/example_target.cmd:
--------------------------------------------------------------------------------
1 | @echo off
2 | echo CMD script called from PSScriptMenuGui.ps1
3 | pause
--------------------------------------------------------------------------------
/PSScriptMenuGui/examples/pwsh7.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dan-osull/PowerShell-Script-Menu-Gui/HEAD/PSScriptMenuGui/examples/pwsh7.ico
--------------------------------------------------------------------------------
/PSScriptMenuGui/xaml/heading.xaml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/PSScriptMenuGui/examples/example_target.ps1:
--------------------------------------------------------------------------------
1 | param ($message)
2 | "PowerShell script called from PSScriptMenuGui.ps1"
3 | if ($message) {
4 | "`$message = $message"
5 | }
6 | $PSVersionTable
7 | Read-Host "Press Enter to continue"
--------------------------------------------------------------------------------
/PSScriptMenuGui/examples/PSScriptMenuGui.ps1:
--------------------------------------------------------------------------------
1 | #region Setup
2 | Set-Location $PSScriptRoot
3 | Remove-Module PSScriptMenuGui -ErrorAction SilentlyContinue
4 | try {
5 | Import-Module PSScriptMenuGui -ErrorAction Stop
6 | }
7 | catch {
8 | Write-Warning $_
9 | Write-Verbose 'Attempting to import from parent directory...' -Verbose
10 | Import-Module '..\'
11 | }
12 | #endregion
13 |
14 | Show-ScriptMenuGui -csvPath '.\example_data.csv' -Verbose
--------------------------------------------------------------------------------
/PSScriptMenuGui/xaml/item.xaml:
--------------------------------------------------------------------------------
1 |
4 | INSERT_DESCRIPTION
--------------------------------------------------------------------------------
/PSScriptMenuGui/examples/PSScriptMenuGui_all_options.ps1:
--------------------------------------------------------------------------------
1 | #region Setup
2 | Set-Location $PSScriptRoot
3 | Remove-Module PSScriptMenuGui -ErrorAction SilentlyContinue
4 | try {
5 | Import-Module PSScriptMenuGui -ErrorAction Stop
6 | }
7 | catch {
8 | Write-Warning $_
9 | Write-Verbose 'Attempting to import from parent directory...' -Verbose
10 | Import-Module '..\'
11 | }
12 | #endregion
13 |
14 | $params = @{
15 | csvPath = '.\example_data.csv'
16 | windowTitle = 'Example with all options'
17 | buttonForegroundColor = 'Azure'
18 | buttonBackgroundColor = '#C00077'
19 | iconPath = '.\pwsh7.ico'
20 | hideConsole = $true
21 | noExit = $true
22 | Verbose = $true
23 | }
24 | Show-ScriptMenuGui @params
--------------------------------------------------------------------------------
/PSScriptMenuGui/PSScriptMenuGui.psm1:
--------------------------------------------------------------------------------
1 | if ($PSEdition -eq 'Core') {
2 | if (-not $IsWindows) {
3 | throw 'This module only runs on Windows'
4 | }
5 | if ($PSVersionTable.PSVersion.Major -eq 6) {
6 | throw 'This module is not compatible with PowerShell Core 6'
7 | }
8 | }
9 |
10 | # Get public and private function definition files
11 | # Based on: https://github.com/RamblingCookieMonster/PSStackExchange/blob/db1277453374cb16684b35cf93a8f5c97288c41f/PSStackExchange/PSStackExchange.psm1
12 | $scripts = @()
13 | $scripts += Get-ChildItem -Path $PSScriptRoot\public\*.ps1 -ErrorAction SilentlyContinue
14 | $scripts += Get-ChildItem -Path $PSScriptRoot\private\*.ps1 -ErrorAction SilentlyContinue
15 |
16 | # Dot source the files
17 | ForEach ($script in $scripts) {
18 | try {
19 | . $script.FullName
20 | }
21 | catch {
22 | throw
23 | }
24 | }
25 |
26 | # Used to get files from xaml and examples subfolders
27 | $moduleRoot = $PSScriptRoot
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Dan O'Sullivan
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/PSScriptMenuGui/examples/example_data.csv:
--------------------------------------------------------------------------------
1 | Section,Method,Command,Arguments,Name,Description
2 | Old school,cmd,.\example_target.cmd,,Example 1:cmd,.cmd file
3 | Old school,cmd,taskmgr.exe,,Example 2:cmd,External executable
4 | Old school,cmd,notepad.exe,example_text_file,Example 3:cmd,External executable with arguments
5 | Less old,powershell_file,.\example_target.ps1,,Example 4:powershell_file,.ps1 file called with powershell.exe
6 | Less old,powershell_inline,"""Inline script"";$PSVersionTable;Read-Host ""Press Enter to continue""",,Example 5:powershell_inline,Inline script called with powershell.exe
7 | Less old,powershell_inline,$PSVersionTable, -NoExit -WindowStyle Maximized,Example 6:powershell_inline,Additional powershell.exe arguments
8 | The future,pwsh_file,.\example_target.ps1,,Example 7:pwsh_file,.ps1 file called with pwsh.exe
9 | The future,pwsh_inline,"""Inline script"";$PSVersionTable;Read-Host ""Press Enter to continue""",,Example 8:pwsh_inline,Inline script called with pwsh.exe
10 | The future,pwsh_inline,"& .\example_target.ps1 -Message ""passed in via param""",,Example 9:pwsh_inline,.ps1 file called with parameter
11 |
--------------------------------------------------------------------------------
/PSScriptMenuGui/xaml/start.xaml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/PSScriptMenuGui/PSScriptMenuGui.psd1:
--------------------------------------------------------------------------------
1 | #
2 | # Module manifest for module 'PSScriptMenuGui'
3 | #
4 | # Generated by: Dan O'Sullivan
5 | #
6 | # Generated on: 10/7/2019
7 | #
8 |
9 | @{
10 |
11 | # Script module or binary module file associated with this manifest.
12 | RootModule = 'PSScriptMenuGui.psm1'
13 |
14 | # Version number of this module.
15 | ModuleVersion = '1.0.1'
16 |
17 | # Supported PSEditions
18 | # CompatiblePSEditions = @()
19 |
20 | # ID used to uniquely identify this module
21 | GUID = '103460b8-4f8b-471c-8f70-41e493070656'
22 |
23 | # Author of this module
24 | Author = "Dan O'Sullivan"
25 |
26 | # Company or vendor of this module
27 | # CompanyName = ''
28 |
29 | # Copyright statement for this module
30 | Copyright = "(c) Dan O'Sullivan. Released under the MIT License."
31 |
32 | # Description of the functionality provided by this module
33 | Description = 'Use a CSV file to make a graphical menu of PowerShell scripts. Easy to customise and fast to launch.
34 |
35 | You can also add Windows programs and files to the menu.
36 |
37 | See the Project Site on GitHub for full documentation.'
38 |
39 | # Minimum version of the PowerShell engine required by this module
40 | PowerShellVersion = '5.1'
41 |
42 | # Name of the PowerShell host required by this module
43 | # PowerShellHostName = ''
44 |
45 | # Minimum version of the PowerShell host required by this module
46 | # PowerShellHostVersion = ''
47 |
48 | # Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
49 | # DotNetFrameworkVersion = ''
50 |
51 | # Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
52 | # CLRVersion = ''
53 |
54 | # Processor architecture (None, X86, Amd64) required by this module
55 | # ProcessorArchitecture = ''
56 |
57 | # Modules that must be imported into the global environment prior to importing this module
58 | # RequiredModules = @()
59 |
60 | # Assemblies that must be loaded prior to importing this module
61 | # RequiredAssemblies = @()
62 |
63 | # Script files (.ps1) that are run in the caller's environment prior to importing this module.
64 | # ScriptsToProcess = @()
65 |
66 | # Type files (.ps1xml) to be loaded when importing this module
67 | # TypesToProcess = @()
68 |
69 | # Format files (.ps1xml) to be loaded when importing this module
70 | # FormatsToProcess = @()
71 |
72 | # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
73 | # NestedModules = @()
74 |
75 | # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
76 | FunctionsToExport = @(
77 | 'Show-ScriptMenuGui',
78 | 'New-ScriptMenuGuiExample'
79 | )
80 |
81 | # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
82 | CmdletsToExport = @()
83 |
84 | # Variables to export from this module
85 | VariablesToExport = '*'
86 |
87 | # Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.
88 | AliasesToExport = @()
89 |
90 | # DSC resources to export from this module
91 | # DscResourcesToExport = @()
92 |
93 | # List of all modules packaged with this module
94 | # ModuleList = @()
95 |
96 | # List of all files packaged with this module
97 | # FileList = @()
98 |
99 | # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
100 | PrivateData = @{
101 |
102 | PSData = @{
103 |
104 | # Tags applied to this module. These help with module discovery in online galleries.
105 | Tags = @('PSEdition_Desktop','PSEdition_Core','Windows')
106 |
107 | # A URL to the license for this module.
108 | LicenseUri = 'https://github.com/weebsnore/PowerShell-Script-Menu-Gui/blob/master/LICENSE'
109 |
110 | # A URL to the main website for this project.
111 | ProjectUri = 'https://github.com/weebsnore/PowerShell-Script-Menu-Gui'
112 |
113 | # A URL to an icon representing this module.
114 | # IconUri = ''
115 |
116 | # ReleaseNotes of this module
117 | # ReleaseNotes = ''
118 |
119 | # Prerelease string of this module
120 | # Prerelease = ''
121 |
122 | # Flag to indicate whether the module requires explicit user acceptance for install/update/save
123 | RequireLicenseAcceptance = $false
124 |
125 | # External dependent modules of this module
126 | # ExternalModuleDependencies = @()
127 |
128 | } # End of PSData hashtable
129 |
130 | } # End of PrivateData hashtable
131 |
132 | # HelpInfo URI of this module
133 | # HelpInfoURI = ''
134 |
135 | # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
136 | # DefaultCommandPrefix = ''
137 |
138 | }
139 |
140 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # PSScriptMenuGui
2 |
3 | [](https://www.powershellgallery.com/packages/PSScriptMenuGui/) [](https://www.powershellgallery.com/packages/PSScriptMenuGui/) [](https://www.powershellgallery.com/packages/PSScriptMenuGui/)
4 |
5 | Do you have favourite scripts that go forgotten?
6 |
7 | Does your organisation have scripts that would be useful to frontline staff who are not comfortable with the command line?
8 |
9 | This module uses a CSV file to make a graphical menu of PowerShell scripts.
10 |
11 | It's easy to customise and fast to launch.
12 |
13 | You can also add Windows programs and files to the menu.
14 |
15 | Just a few minutes to setup and - *click! click!* - you're away!
16 |
17 | 
18 |
19 | ## Try it out
20 |
21 | ### Tutorial
22 |
23 | Looking for a step-by-step introduction? [**See this blog post.**](https://blog.osull.com/2019/11/06/tutorial-use-a-csv-file-to-make-a-graphical-menu-of-powershell-scripts/)
24 |
25 | ### Install from the PowerShell Gallery
26 |
27 | Install-Module PSScriptMenuGui -Scope CurrentUser
28 | New-ScriptMenuGuiExample
29 | cd PSScriptMenuGui_example
30 | .\PSScriptMenuGui.ps1
31 |
32 | ### Clone from GitHub
33 |
34 | git clone https://github.com/weebsnore/PowerShell-Script-Menu-Gui
35 | cd PowerShell-Script-Menu-Gui\PSScriptMenuGui\examples
36 | .\PSScriptMenuGui.ps1
37 |
38 | ## Problems and feedback
39 |
40 | How are you finding the module? Is it useful? *(Please share a screenshot!)*
41 |
42 | Are you stuck? Do you want a feature?
43 |
44 | Please [open a GitHub issue](https://github.com/weebsnore/PowerShell-Script-Menu-Gui/issues) or get in touch.
45 |
46 | [@dan_osull.com](https://twitter.com/dan_osull_com/) *- follow me for updates!*
47 | https://blog.osull.com
48 | powershell@osull.com
49 |
50 | ## Compatibility
51 |
52 | Tested with **PowerShell 5.1 x64** and **PowerShell 7 x64** on Windows 10.
53 |
54 | ## Basic usage
55 |
56 | Show-ScriptMenuGui -csvPath '.\example_data.csv' -Verbose
57 |
58 | ## Show-ScriptMenuGui options
59 |
60 | Parameter | What is it?
61 | :--- |:---
62 | `-csvPath` | Path to CSV file that defines the menu. See [CSV reference](#csv-reference), below.
63 | `-windowTitle` *(optional)* | Custom title for the menu window
64 | `-buttonForegroundColor` *(optional)* | Custom button foreground (text) color. Hex codes (e.g. `#C00077`) and color names (e.g. `Azure`) are valid. See [.NET Color Class](https://docs.microsoft.com/en-us/dotnet/api/system.windows.media.colors).
65 | `-buttonBackgroundColor` *(optional)* | Custom button background color
66 | `-iconPath` *(optional)* | Path to .ico file for use in menu
67 | `-hideConsole` *(optional)* | Hide the PowerShell console that the menu is called from. **Note:** This means you won't be able to see any errors from button clicks. If things aren't working, this should be the first thing you stop using.
68 | `-noExit` *(optional)* | Start all PowerShell instances with `-NoExit` *("Does not exit after running startup commands.")*. **Note:** You can set `-NoExit` on individual menu items by using the *Arguments* column. See [CSV reference](#csv-reference), below.
69 |
70 | See [`PSScriptMenuGui_all_options.ps1`](PSScriptMenuGui/examples/PSScriptMenuGui_all_options.ps1) for an example using every option.
71 |
72 | ## CSV reference
73 |
74 | This table details how to lay out the CSV file for your menu.
75 |
76 | The top row of your CSV should contain the column headers. Each row after this defines a menu item.
77 |
78 | Column header | What is it?
79 | :--- |:---
80 | Section *(optional)* | Text for heading
81 | Method | What happens when you click the button? Valid options: `cmd` \| `powershell_file` \| `powershell_inline` \| `pwsh_file` \| `pwsh_inline`
82 | Command | Path to target script/executable (`cmd` or `_file` methods) ***or*** PowerShell commands (`_inline` methods)
83 | Arguments *(optional)* | Arguments to pass to target executable (`cmd` method) ***or*** to the PowerShell exe (other methods)
84 | Name | Text for button
85 | Description *(optional)* | Text for description
86 |
87 | ### Some examples
88 |
89 | Section | Method | Command | Arguments | Name | Description
90 | :---|:---|:---|:---|:---|:---
91 | Old school | `cmd` | `taskmgr.exe` | | Example 2: cmd | External executable
92 | Old school | `cmd` | `notepad.exe` | `example_text_file` | Example 3: cmd | External executable with arguments
93 | Less old | `powershell_file` | `example_target.ps1` | | Example 4: powershell_file | .ps1 file called with powershell.exe
94 | Less old | `powershell_inline` | `$PSVersionTable` | `-NoExit -WindowStyle Maximized` | Example 6: powershell_inline | Additional powershell.exe arguments
95 | The future | `pwsh_file` | `example_target.ps1` | | Example 7: pwsh_file | .ps1 file called with pwsh.exe
96 | The future | `pwsh_inline` | `& .\example_target.ps1 -Message "passed in via param"` | |Example 9: pwsh_inline | .ps1 file called with parameter
97 |
98 | See [`example_data.csv`](PSScriptMenuGui/examples/example_data.csv) for further examples in CSV format.
99 |
100 | ### Tips
101 |
102 | - Relative paths, network paths and paths in your environment should work.
103 | - `` is supported in text fields.
104 | - You can add multiple `_inline` commands by separating with a semi-colon (`;`)
105 | - Excel makes a good editor!
106 | - But watch out for Excel turning e.g. `-NoExit` into a formula. Best workaround is to prefix with a space.
107 |
108 | 
109 |
--------------------------------------------------------------------------------
/PSScriptMenuGui/public/functions.ps1:
--------------------------------------------------------------------------------
1 | Function Show-ScriptMenuGui {
2 | <#
3 | .SYNOPSIS
4 | Use a CSV file to make a graphical menu of PowerShell scripts. Easy to customise and fast to launch.
5 | .DESCRIPTION
6 | Do you have favourite scripts that go forgotten?
7 |
8 | Does your organisation have scripts that would be useful to frontline staff who are not comfortable with the command line?
9 |
10 | This module uses a CSV file to make a graphical menu of PowerShell scripts.
11 |
12 | You can also add Windows programs and files to the menu.
13 | .PARAMETER csvPath
14 | Path to CSV file that defines the menu.
15 |
16 | See CSV reference: https://github.com/weebsnore/PowerShell-Script-Menu-Gui
17 | .PARAMETER windowTitle
18 | Custom title for the menu window.
19 | .PARAMETER buttonForegroundColor
20 | Custom button foreground (text) color.
21 |
22 | Hex codes (e.g. #C00077) and color names (e.g. Azure) are valid.
23 |
24 | See .NET Color Class: https://docs.microsoft.com/en-us/dotnet/api/system.windows.media.colors
25 | .PARAMETER buttonBackgroundColor
26 | Custom button background color.
27 | .PARAMETER iconPath
28 | Path to .ico file for use in menu.
29 | .PARAMETER hideConsole
30 | Hide the PowerShell console that the menu is called from.
31 |
32 | Note: This means you won't be able to see any errors from button clicks. If things aren't working, this should be the first thing you stop using.
33 | .PARAMETER noExit
34 | Start all PowerShell instances with -NoExit ("Does not exit after running startup commands.")
35 |
36 | Note: You can set -NoExit on individual menu items by using the Arguments column.
37 |
38 | See CSV reference: https://github.com/weebsnore/PowerShell-Script-Menu-Gui
39 | .EXAMPLE
40 | Show-ScriptMenuGui -csvPath '.\example_data.csv' -Verbose
41 | .NOTES
42 | Run New-ScriptMenuGuiExample to get some example files
43 | .LINK
44 | https://github.com/weebsnore/PowerShell-Script-Menu-Gui
45 | #>
46 | [CmdletBinding()]
47 | param(
48 | [string][Parameter(Mandatory)]$csvPath,
49 | [string]$windowTitle = 'PowerShell Script Menu',
50 | [string]$buttonForegroundColor = 'White',
51 | [string]$buttonBackgroundColor = '#366EE8',
52 | [string]$iconPath,
53 | [switch]$hideConsole,
54 | [switch]$noExit
55 | )
56 | Write-Verbose 'Show-ScriptMenuGui started'
57 |
58 | # -Verbose value, to pass to select cmdlets
59 | $verbose = $false
60 | try {
61 | if ($PSBoundParameters['Verbose'].ToString() -eq 'True') {
62 | $verbose = $true
63 | }
64 | }
65 | catch {}
66 |
67 | $csvData = Import-CSV -Path $csvPath -ErrorAction Stop
68 | Write-Verbose "Got $($csvData.Count) CSV rows"
69 |
70 | # Add unique Reference to each item
71 | # Used as x:Name of button and to look up action on click
72 | $i = 0
73 | $csvData | ForEach-Object {
74 | $_ | Add-Member -Name Reference -MemberType NoteProperty -Value "button$i"
75 | $i++
76 | }
77 |
78 | # Begin constructing XAML
79 | $xaml = Get-Content "$moduleRoot\xaml\start.xaml"
80 | $xaml = $xaml.Replace('INSERT_WINDOW_TITLE',$windowTitle)
81 | if ($iconPath) {
82 | # TODO: change taskbar icon?
83 | # WPF wants the absolute path
84 | $iconPath = (Resolve-Path $iconPath).Path
85 | $xaml = $xaml.Replace('INSERT_ICON_PATH',$iconPath)
86 | }
87 | else {
88 | # No icon specified
89 | $xaml = $xaml.Replace('Icon="INSERT_ICON_PATH" ','')
90 | }
91 |
92 | # Add CSV data to XAML
93 | # Row counter
94 | $script:row = 0
95 | # Not using Group-Object as PS7-preview4 does not preserve original order
96 | $sections = $csvData.Section | Where-Object {-not [string]::IsNullOrEmpty($_) } | Get-Unique
97 | # Generate GUI rows
98 | ForEach ($section in $sections) {
99 | Write-Verbose "Adding GUI Section: $section..."
100 | # Section Heading
101 | $xaml += New-GuiHeading $section
102 | $csvData | Where-Object {$_.Section -eq $section} | ForEach-Object {
103 | # Add items
104 | $xaml += New-GuiRow $_
105 | }
106 | }
107 | Write-Verbose 'Adding any items with blank Section...'
108 | $csvData | Where-Object { [string]::IsNullOrEmpty($_.Section) } | ForEach-Object {
109 | $xaml += New-GuiRow $_
110 | # TODO: spacing at top of window is untidy with no Sections (minor)
111 | }
112 | Write-Verbose "Added $($row) GUI rows"
113 |
114 | # Finish constructing XAML
115 | $xaml += Get-Content "$moduleRoot\xaml\end.xaml"
116 |
117 | Write-Verbose 'Creating XAML objects...'
118 | $form = New-GuiForm -inputXml $xaml
119 |
120 | Write-Verbose "Found $($buttons.Count) buttons"
121 | Write-Verbose 'Adding click actions...'
122 | ForEach ($button in $buttons) {
123 | $button.Add_Click( {
124 | # Use object in pipeline to identify script to run
125 | Invoke-ButtonAction $_.Source.Name
126 | } )
127 | }
128 |
129 | if ($hideConsole) {
130 | if ($global:error[0].Exception.CommandInvocation.MyCommand.ModuleName -ne 'PSScriptMenuGui') {
131 | # Do not hide console if there have been errors
132 | Hide-Console | Out-Null
133 | }
134 | }
135 |
136 | Write-Verbose 'Showing dialog...'
137 | $Form.ShowDialog() | Out-Null
138 | }
139 |
140 | Function New-ScriptMenuGuiExample {
141 | <#
142 | .SYNOPSIS
143 | Creates an example set of files for PSScriptMenuGui
144 | .PARAMETER path
145 | Path of output folder
146 | .EXAMPLE
147 | New-ScriptMenuGuiExample -path 'PSScriptMenuGui_example'
148 | .LINK
149 | https://github.com/weebsnore/PowerShell-Script-Menu-Gui
150 | #>
151 | [CmdletBinding()]
152 | param (
153 | [string]$path = 'PSScriptMenuGui_example'
154 | )
155 |
156 | # Ensure folder exists
157 | if (-not (Test-Path -Path $path -PathType Container) ) {
158 | New-Item -Path $path -ItemType 'directory' -Verbose | Out-Null
159 | }
160 |
161 | Write-Verbose "Copying example files to $path..." -Verbose
162 | Copy-Item -Path "$moduleRoot\examples\*" -Destination $path
163 | }
--------------------------------------------------------------------------------
/PSScriptMenuGui/private/functions.ps1:
--------------------------------------------------------------------------------
1 | function Hide-Console {
2 | Write-Verbose 'Hiding PowerShell console...'
3 | # .NET method for hiding the PowerShell console window
4 | # https://stackoverflow.com/questions/40617800/opening-powershell-script-and-hide-command-prompt-but-not-the-gui
5 | Add-Type -Name Window -Namespace Console -MemberDefinition '
6 | [DllImport("Kernel32.dll")]
7 | public static extern IntPtr GetConsoleWindow();
8 |
9 | [DllImport("user32.dll")]
10 | public static extern bool ShowWindow(IntPtr hWnd, Int32 nCmdShow);
11 | '
12 | $consolePtr = [Console.Window]::GetConsoleWindow()
13 | [Console.Window]::ShowWindow($consolePtr, 0) # 0 = hide
14 | }
15 |
16 | Function New-GuiHeading {
17 | param(
18 | [Parameter(Mandatory)][string]$name
19 | )
20 | $string = Get-Content "$moduleRoot\xaml\heading.xaml"
21 | $string = $string.Replace('INSERT_SECTION_HEADING',(Get-XamlSafeString $name) )
22 | $string = $string.Replace('INSERT_ROW',$row)
23 | $script:row++
24 |
25 | return $string
26 | }
27 |
28 | Function New-GuiRow {
29 | [CmdletBinding()]
30 | param(
31 | [Parameter(Mandatory)][PSCustomObject]$item
32 | )
33 | Write-Verbose $item
34 |
35 | $string = Get-Content "$moduleRoot\xaml\item.xaml"
36 | $string = $string.Replace('INSERT_BACKGROUND_COLOR',$buttonBackgroundColor)
37 | $string = $string.Replace('INSERT_FOREGROUND_COLOR',$buttonForegroundColor)
38 | $string = $string.Replace('INSERT_BUTTON_TEXT',(Get-XamlSafeString $item.Name) )
39 | # Description is optional
40 | if ($item.Description) {
41 | $string = $string.Replace('INSERT_DESCRIPTION',(Get-XamlSafeString $item.Description) )
42 | }
43 | else {
44 | $string = $string.Replace('INSERT_DESCRIPTION','')
45 | }
46 | $string = $string.Replace('INSERT_BUTTON_NAME',$item.Reference)
47 | $string = $string.Replace('INSERT_ROW',$row)
48 | $script:row++
49 |
50 | return $string
51 | }
52 |
53 | Function Get-XamlSafeString {
54 | param(
55 | [Parameter(Mandatory)][string]$string
56 | )
57 | # https://docs.microsoft.com/en-us/dotnet/framework/wpf/advanced/how-to-use-special-characters-in-xaml
58 | # Order matters: & first
59 | $string = $string.Replace('&','&').Replace('<','<').Replace('>','>').Replace('"','"')
60 | # Restore line breaks
61 | $string = $string -replace '<\s*?LineBreak\s*?\/\s*?>',''
62 |
63 | return $string
64 | }
65 |
66 | Function New-GuiForm {
67 | # Based on: https://foxdeploy.com/2015/05/14/part-iii-using-advanced-gui-elements-in-powershell/
68 | param (
69 | [Parameter(Mandatory)][array]$inputXml # XML has not been converted to object yet
70 | )
71 | # Process raw XML
72 | $inputXML = $inputXML -replace 'mc:Ignorable="d"','' -replace "x:N",'N' -replace '^