Stannellc icon

FirewallState

Stannellc | PRO | 08/19/26 02:22:02 PM UTC (Edited) | 0 ⭐ | 2363 👁️ | Never ⏰ | []
PowerShell |

9.84 KB

|

Source Code

|

0 👍

/

0 👎

<#
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()

Comments