if (-not (Get-Module -ListAvailable -Name powershell-yaml)) { Install-Module -Scope CurrentUser powershell-yaml } Import-Module powershell-yaml # Add-StructuredTray # by Tobias Simetsreiter # .Net methods for hiding/showing the console in the background Add-Type -ReferencedAssemblies "System.Drawing" -Language CSharp @" using System.Drawing; using System.Runtime.InteropServices; using System; namespace Console { public class Window { [DllImport("Kernel32.dll")] public static extern IntPtr GetConsoleWindow(); [DllImport("user32.dll")] public static extern bool ShowWindow(IntPtr hWnd, Int32 nCmdShow); } } "@; [Int]$global:ConsoleVisible = $true Function Toggle-Console(){ $consolePtr = [Console.Window]::GetConsoleWindow() $visible = (-not $global:ConsoleVisible) $global:ConsoleVisible = $visible $visible | Out-Host [Console.Window]::ShowWindow($consolePtr, [Int]$visible) } # Add assemblies for WPF and Mahapps Add-Type -AssemblyName "System.Windows.Forms" Add-Type -AssemblyName "System.Drawing" Add-Type -AssemblyName "presentationframework" Add-Type -AssemblyName "WindowsFormsIntegration" Function Add-StructuredTray{ param( [Parameter(ValueFromPipeline=$true)] [PSCustomObject[]]$definition, $ParentTray = $null, [String]$Config ) BEGIN { $ErrorActionPreference = "Stop" } PROCESS { $Script:TopTray = $false if (-not $definition){ $definition = Get-Content $Config -Raw | ConvertFrom-Yaml } if ($null -eq $ParentTray){ # Hide Console if ($definition.HideConsole -eq $true){ Toggle-Console } # Add the systray icon if ($definition.Icon){ $icon = [System.Drawing.Icon]::ExtractAssociatedIcon($definition.Icon) } else { $icon = [System.Drawing.Icon]::ExtractAssociatedIcon((Get-Command cmd.exe).source) } $Script:Tray_Icon = New-Object System.Windows.Forms.NotifyIcon $Script:Tray_Icon.Text = $definition.Title $Script:Tray_Icon.Icon = $icon $Script:Tray_Icon.Visible = $true $Host.UI.RawUI.WindowTitle = $definition.Title # Add all menus as context menus $ParentTray = New-Object System.Windows.Forms.ContextMenu $Script:TopTray = $ParentTray $Script:Tray_Icon.ContextMenu = $ParentTray $Script:Tray_Icon.add_Click({ # [System.Windows.Forms.Integration.ElementHost]::EnableModelessKeyboardInterop($Users_Window) # If ($_.Button -eq [Windows.Forms.MouseButtons]::Left) { # "Clicked" | Out-Host # } }) if ($definition.MenuItems){ $definition.MenuItems | Add-StructuredTray -Parent $ParentTray } $Menu_Exit = New-Object System.Windows.Forms.MenuItem $Menu_Exit.Text = "Exit" $Menu_Exit.add_Click({ $Script:Tray_Icon.Visible = $false $Script:Tray_Icon.Dispose() $Script:appContext.ExitThread() }) $ParentTray.MenuItems.AddRange($Menu_Exit) # Use a Garbage colection to reduce Memory RAM [System.GC]::Collect() $Script:appContext = New-Object System.Windows.Forms.ApplicationContext [void][System.Windows.Forms.Application]::Run($Script:appContext) $Script:Tray_Icon.Visible = $false $Script:Tray_Icon.Dispose() } else { $Menu_Script = New-Object System.Windows.Forms.MenuItem $Menu_Script.Text = $definition.Text $Menu_Script.Tag = $definition if ($null -ne $definition.Enabled){ $Menu_Script.Enabled = $definition.Enabled } if ($definition.Command){ $Menu_Script.add_Click({ Param ($com) $com.Tag.Command | Out-host if ($com.Tag.NewWindow -eq $true){ Start-Process powershell -ArgumentList ("-ExecutionPolicy", "Bypass", "-noprofile", $com.Tag.Command) } else { $return = Invoke-Expression $com.Tag.Command } if ($com.Tag.Notification){ $Script:Tray_Icon.BalloonTipIcon = [System.Windows.Forms.ToolTipIcon]::Info $Script:Tray_Icon.BalloonTipText = $return $Script:Tray_Icon.BalloonTipTitle = $com.Tag.Text $Script:Tray_Icon.ShowBalloonTip(5000) } else { $return | Out-Host } }) } $ParentTray.MenuItems.AddRange($Menu_Script) if ($definition.MenuItems){ $definition.MenuItems | Add-StructuredTray -Parent $Menu_Script } } } }