Public/Start-PSSysTray.ps1


<#PSScriptInfo
 
.VERSION 0.1.0
 
.GUID 41aa308f-60e2-499b-aa12-a92e73f4a1c1
 
.AUTHOR Pierre Smit
 
.COMPANYNAME iOCO Tech
 
.COPYRIGHT
 
.TAGS ps
 
.LICENSEURI
 
.PROJECTURI
 
.ICONURI
 
.EXTERNALMODULEDEPENDENCIES
 
.REQUIREDSCRIPTS
 
.EXTERNALSCRIPTDEPENDENCIES
 
.RELEASENOTES
Created [24/10/2021_05:59] Initital Script Creating
 
.PRIVATEDATA
 
#>


<#
 
.DESCRIPTION
 Gui menu app in your systray with custom executable functions
 
#>
 
#.ExternalHelp PSLauncher-help.xml

Function Start-PSSysTray {

    <#
.SYNOPSIS
Gui menu app in your systray with custom executable functions
 
.DESCRIPTION
Gui menu app in your systray with custom executable functions
 
.PARAMETER ConfigFilePath
Path to .csv config file created from Install-PSSysTrayConfigFile
 
.EXAMPLE
Start-PSSysTray -ConfigFilePath C:\temp\PSSysTrayConfig.csv
 
#>

    [Cmdletbinding()]
 Param (
        [Parameter(Mandatory = $true, Position = 0)]
        [ValidateScript( { (Test-Path $_) -and ((Get-Item $_).Extension -eq '.csv') })]
        [string]$ConfigFilePath
    ) 
    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);
'


    # Declare assemblies
    [System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms') | Out-Null
    [System.Reflection.Assembly]::LoadWithPartialName('presentationframework') | Out-Null 
    [System.Reflection.Assembly]::LoadWithPartialName('System.Drawing') | Out-Null
    [System.Reflection.Assembly]::LoadWithPartialName('WindowsFormsIntegration') | Out-Null
 
    # Add an icon to the systrauy button
    $icopath = (Join-Path (Get-Module PSLauncher).ModuleBase '\Private\pslauncher.ico') | Get-Item
    $icon = [System.Drawing.Icon]::ExtractAssociatedIcon($icopath.FullName)
 
    # Create object for the systray
    $Systray_Tool_Icon = New-Object System.Windows.Forms.NotifyIcon
    # Text displayed when you pass the mouse over the systray icon
    $Systray_Tool_Icon.Text = 'PS Utils'
    # Systray icon
    $Systray_Tool_Icon.Icon = $icon
    $Systray_Tool_Icon.Visible = $true
    $contextmenu = New-Object System.Windows.Forms.ContextMenu
    $Systray_Tool_Icon.ContextMenu = $contextmenu

    function Start-ShowConsole {
        $PSConsole = [Console.Window]::GetConsoleWindow()
        [Console.Window]::ShowWindow($PSConsole, 5)
    }
    function Start-HideConsole {
        $PSConsole = [Console.Window]::GetConsoleWindow()
        [Console.Window]::ShowWindow($PSConsole, 0)
    }
    function New-MenuItem {
        param(
            [string]$Text = 'Placeholder Text',
            $MyScriptPath,
            [ValidateSet('PSFile', 'PSCommand', 'Other')]
            [string]$method,
            [System.Windows.Forms.MenuItem]$MainMenu
        )

        #Initialization
        $MenuItem = New-Object System.Windows.Forms.MenuItem

        #Apply desired text
        if ($Text) {
            $MenuItem.Text = $Text
        }

        #Apply click event logic
        if ($MyScriptPath -and !$ExitOnly) {
            $MenuItem | Add-Member -Name MyScriptPath -Value $MyScriptPath -MemberType NoteProperty
            if ($method -eq 'PSFile') {
                $MenuItem.Add_Click( {
                        Start-ShowConsole
                        $MyScriptPath = $This.MyScriptPath #Used to find proper path during click event
                        Start-Process -FilePath 'C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe' -ArgumentList "-NoProfile -NoLogo -ExecutionPolicy Bypass -File `"$MyScriptPath`"" -ErrorAction Stop
                        Start-HideConsole
                    })
            }
                
            if ($method -eq 'PSCommand') {
                $MenuItem.Add_Click( {
                        Start-ShowConsole
                        $MyScriptPath = $This.MyScriptPath #Used to find proper path during click event
                        Start-Process -FilePath 'C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe' -ArgumentList "-NoProfile -NoLogo -ExecutionPolicy Bypass -Command `"& {$MyScriptPath}""" -ErrorAction Stop
                        Start-HideConsole
                    })
            }
            if ($method -eq 'Other') {
                $MenuItem.Add_Click( {
                        Start-ShowConsole
                        $MyScriptPath = $This.MyScriptPath #Used to find proper path during click event
                        Start-Process $MyScriptPath
                        Start-HideConsole

                    })
            }
        
        }

        #Return our new MenuItem
        $MainMenu.MenuItems.AddRange($MenuItem)
    }
    function New-MainMenu {
        param(
            [string]$Text = 'Placeholder Text',
            [switch]$AddExit = $false
        )
        $MainMenu = New-Object System.Windows.Forms.MenuItem
        $MainMenu.Text = $Text
        $Systray_Tool_Icon.contextMenu.MenuItems.AddRange($MainMenu)
        $MainMenu

        if ($AddExit) {
            $Menu_Exit = New-Object System.Windows.Forms.MenuItem
            $Menu_Exit.Text = 'Exit'
            $Menu_Exit.add_Click( {
                    $Systray_Tool_Icon.Visible = $false
                    $window.Close()
                    # $window_Config.Close()
                    Stop-Process $pid
                })
            $Systray_Tool_Icon.contextMenu.MenuItems.AddRange($Menu_Exit)
        }
    }

    $config = Import-Csv -Path $ConfigFilePath    
    foreach ($main in ($config.mainmenu | Get-Unique)) {
        $tmpmenu = New-MainMenu -Text $main
        $config | Where-Object { $_.Mainmenu -like $main } | ForEach-Object { New-MenuItem -Text $_.ScriptName -MyScriptPath $_.ScriptPath -method $_.mode -MainMenu $tmpmenu }
    }
    $Menu_Exit = New-Object System.Windows.Forms.MenuItem
    $Menu_Exit.Text = 'Exit'
    $Menu_Exit.add_Click( {
            $Systray_Tool_Icon.Visible = $false
            $window.Close()
            $window_Config.Close() 
            Stop-Process $pid
        })
    $Systray_Tool_Icon.contextMenu.MenuItems.AddRange($Menu_Exit)


    # Create an application context for it to all run within.
    # This helps with responsiveness, especially when clicking Exit.
    Start-HideConsole
    $appContext = New-Object System.Windows.Forms.ApplicationContext
    [void][System.Windows.Forms.Application]::Run($appContext)



} #end Function