<# I had a need to be able to turn Windows Defender firewall on/off at will and it was getting to be a pain. This script will give you a tray icon you can use. Click on, click off. In case you forget, it includes a timer that will turn it back on after you disable it in case you forget. Options on right click context menu: Disable for 5min, 15min, 1hr and an option to add 5min increments Sound alert that plays when firewall re-enables. Can be customized. Tool tip shows a countdown to enable time. SS - NovaWright Studios #> # ========================================================================= # CONFIGURATION SETTINGS # ========================================================================= # Set to $true to show the system tray icon # Set to $false to hide the icon completely (runs silently in background) $showTrayIcon = $true # Default disable duration in minutes when left-clicking icon $defaultDisableMinutes = 10 # Set to $true to play an audio alert when the firewall auto-enables $enableSoundAlert = $true # Path to a custom .wav sound file. If left empty "" or file is not found, falls back to Windows system sounds. $customWavPath = "" # ========================================================================= Add-Type -AssemblyName System.Windows.Forms Add-Type -AssemblyName System.Drawing # Ensure script runs with Administrator privileges if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" -Verb RunAs exit } # Create System Tray Icon $notifyIcon = New-Object System.Windows.Forms.NotifyIcon # Set Tray Icon Visibility based on configuration above $notifyIcon.Visible = $showTrayIcon # Global Target Time, Warning State, & 1-Second Timer Initialization $script:endTime = [DateTime]::MinValue $script:warnedOneMinute = $false $autoEnableTimer = New-Object System.Windows.Forms.Timer $autoEnableTimer.Interval = 1000 # Ticks every 1 second to update countdown # Helper function to play custom .wav or fallback system sound function Play-AlertSound ([string]$systemSoundType = "Asterisk", [bool]$ignoreAlertToggle = $false) { if (-not $enableSoundAlert -and -not $ignoreAlertToggle) { return } if (-not [string]::IsNullOrWhiteSpace($customWavPath) -and (Test-Path $customWavPath)) { try { $player = New-Object System.Media.SoundPlayer($customWavPath) $player.Play() # Asynchronous playback } catch { [System.Media.SystemSounds]::$systemSoundType.Play() } } else { if ($systemSoundType -eq "Exclamation") { [System.Media.SystemSounds]::Exclamation.Play() } else { [System.Media.SystemSounds]::Asterisk.Play() } } } # Helper function to query live state and update Icon + Tooltip function Update-FirewallState { $isEnabled = (Get-NetFirewallProfile -Profile Domain).Enabled if ($isEnabled) { $notifyIcon.Icon = [System.Drawing.SystemIcons]::Shield $notifyIcon.Text = "Firewall: ENABLED (Click to disable for ${defaultDisableMinutes}m)" } else { $notifyIcon.Icon = [System.Drawing.SystemIcons]::Warning $remaining = $script:endTime - [DateTime]::Now if ($remaining.TotalSeconds -gt 0) { if ($remaining.TotalHours -ge 1) { $timeLeft = "{0:D2}:{1:D2}:{2:D2}" -f [math]::Floor($remaining.TotalHours), $remaining.Minutes, $remaining.Seconds } else { $timeLeft = "{0:D2}:{1:D2}" -f $remaining.Minutes, $remaining.Seconds } $notifyIcon.Text = "Firewall: DISABLED ($timeLeft left)" } else { $notifyIcon.Text = "Firewall: DISABLED" } } } # Function to turn firewall ON function Enable-Firewall ([string]$source = "manual") { Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled True $autoEnableTimer.Stop() $script:warnedOneMinute = $false Update-FirewallState if ($source -eq "timer") { Play-AlertSound -systemSoundType "Asterisk" if ($showTrayIcon) { $notifyIcon.ShowBalloonTip(4000, "Windows Firewall Restored", "Disable timer expired. Firewall auto-enabled.", [System.Windows.Forms.ToolTipIcon]::Info) } } else { if ($showTrayIcon) { $notifyIcon.ShowBalloonTip(3000, "Windows Firewall Enabled", "Firewall ENABLED. Protection active.", [System.Windows.Forms.ToolTipIcon]::Info) } } } # Function to turn firewall OFF and start timer function Disable-Firewall ([int]$minutes = $defaultDisableMinutes) { Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled False $script:endTime = [DateTime]::Now.AddMinutes($minutes) $script:warnedOneMinute = $false $autoEnableTimer.Start() Update-FirewallState if ($showTrayIcon) { $notifyIcon.ShowBalloonTip(4000, "Windows Firewall Disabled", "Firewall DISABLED. Auto-enables in ${minutes}m.", [System.Windows.Forms.ToolTipIcon]::Warning) } } # Timer Event (Fires every second) $autoEnableTimer.add_Tick({ $remaining = $script:endTime - [DateTime]::Now if ($remaining.TotalSeconds -gt 0) { if ($remaining.TotalSeconds -le 60 -and -not $script:warnedOneMinute) { $script:warnedOneMinute = $true Play-AlertSound -systemSoundType "Exclamation" if ($showTrayIcon) { $notifyIcon.ShowBalloonTip(4000, "Firewall Auto-Enable Warning", "1 minute remaining until Firewall re-enables.", [System.Windows.Forms.ToolTipIcon]::Warning) } } Update-FirewallState } else { Enable-Firewall -source "timer" } }) # Dedicated Left-Click Event Handler $notifyIcon.add_MouseClick({ param($sender, $e) if ($e.Button -eq [System.Windows.Forms.MouseButtons]::Left) { $currentState = (Get-NetFirewallProfile -Profile Domain).Enabled if ($currentState) { Disable-Firewall -minutes $defaultDisableMinutes } else { Enable-Firewall -source "manual" } } }) # --- RIGHT-CLICK CONTEXT MENU --- $contextMenu = New-Object System.Windows.Forms.ContextMenuStrip # "Disable For..." Submenu $presetMenu = New-Object System.Windows.Forms.ToolStripMenuItem("Disable For...") $item15 = $presetMenu.DropDownItems.Add("15 Minutes") $item15.add_Click({ Disable-Firewall -minutes 15 }) $item30 = $presetMenu.DropDownItems.Add("30 Minutes") $item30.add_Click({ Disable-Firewall -minutes 30 }) $item60 = $presetMenu.DropDownItems.Add("1 Hour") $item60.add_Click({ Disable-Firewall -minutes 60 }) $null = $contextMenu.Items.Add($presetMenu) # "Add 5 Minutes" Option $extendItem = $contextMenu.Items.Add("Add 5 Minutes") $extendItem.add_Click({ $currentState = (Get-NetFirewallProfile -Profile Domain).Enabled if (-not $currentState) { $script:endTime = $script:endTime.AddMinutes(5) if (($script:endTime - [DateTime]::Now).TotalSeconds -gt 60) { $script:warnedOneMinute = $false } Update-FirewallState if ($showTrayIcon) { $notifyIcon.ShowBalloonTip(3000, "Timer Extended", "Added 5 minutes to the firewall disable timer.", [System.Windows.Forms.ToolTipIcon]::Info) } } }) $null = $contextMenu.Items.Add("-") # Separator line # --- SOUND ALERTS SUBMENU --- $soundMenu = New-Object System.Windows.Forms.ToolStripMenuItem("Sound Alerts") # Toggle Enable/Disable Sounds $toggleSoundItem = $soundMenu.DropDownItems.Add("Enable Audio Chimes") $toggleSoundItem.CheckOnClick = $true $toggleSoundItem.Checked = $enableSoundAlert $toggleSoundItem.add_Click({ $script:enableSoundAlert = $toggleSoundItem.Checked }) # Test Sound Action $testSoundItem = $soundMenu.DropDownItems.Add("Test Sound Alert") $testSoundItem.add_Click({ # Forces sound playback even if audio chimes are currently muted Play-AlertSound -systemSoundType "Asterisk" -ignoreAlertToggle $true }) $null = $soundMenu.DropDownItems.Add("-") # Submenu Separator # Select Custom Sound File $selectWavItem = $soundMenu.DropDownItems.Add("Select Custom .WAV Sound...") $selectWavItem.add_Click({ $dialog = New-Object System.Windows.Forms.OpenFileDialog $dialog.Filter = "WAV Audio Files (*.wav)|*.wav" $dialog.Title = "Select Audio Alert Sound" if ($dialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) { $script:customWavPath = $dialog.FileName # Auto-play sound test on selection Play-AlertSound -systemSoundType "Asterisk" -ignoreAlertToggle $true } }) # Reset to Windows Default System Sound $resetWavItem = $soundMenu.DropDownItems.Add("Use Default System Sound") $resetWavItem.add_Click({ $script:customWavPath = "" Play-AlertSound -systemSoundType "Asterisk" -ignoreAlertToggle $true }) $null = $contextMenu.Items.Add($soundMenu) $null = $contextMenu.Items.Add("-") # Separator line $exitItem = $contextMenu.Items.Add("Exit") # Context menu dynamic update handler when opened $contextMenu.add_Opening({ $currentState = (Get-NetFirewallProfile -Profile Domain).Enabled # Only allow "Add 5 Minutes" when firewall is currently disabled $extendItem.Enabled = -not $currentState # Update sound menu checkmark state $toggleSoundItem.Checked = $script:enableSoundAlert }) $exitItem.add_Click({ $autoEnableTimer.Stop() $notifyIcon.Visible = $false [System.Windows.Forms.Application]::Exit() }) $notifyIcon.ContextMenuStrip = $contextMenu # Initial state load Update-FirewallState # Keep script running in background [System.Windows.Forms.Application]::Run()