├── .github ├── FUNDING.yml └── README.md ├── .gitignore └── BlockFolderWindowsFirewall.ps1 /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [asheroto] 2 | ko_fi: asheroto 3 | -------------------------------------------------------------------------------- /.github/README.md: -------------------------------------------------------------------------------- 1 | [![PowerShell Gallery Downloads](https://img.shields.io/powershellgallery/dt/BlockFolderWindowsFirewall?label=PowerShell%20Gallery%20downloads)](https://www.powershellgallery.com/packages/BlockFolderWindowsFirewall) 2 | [![GitHub Downloads - All Releases](https://img.shields.io/github/downloads/asheroto/BlockFolderWindowsFirewall/total?label=release%20downloads)](https://github.com/asheroto/BlockFolderWindowsFirewall/releases) 3 | [![Release](https://img.shields.io/github/v/release/asheroto/BlockFolderWindowsFirewall)](https://github.com/asheroto/BlockFolderWindowsFirewall/releases) 4 | [![GitHub Release Date - Published_At](https://img.shields.io/github/release-date/asheroto/BlockFolderWindowsFirewall)](https://github.com/asheroto/BlockFolderWindowsFirewall/releases) 5 | 6 | [![GitHub Sponsor](https://img.shields.io/github/sponsors/asheroto?label=Sponsor&logo=GitHub)](https://github.com/sponsors/asheroto?frequency=one-time&sponsor=asheroto) 7 | Ko-Fi Button 8 | 9 | 10 | # Block Entire Folder in Windows Firewall 11 | 12 | This script provides functionalities to manage (block/unblock) executables (EXEs) in specified directories via Windows Firewall. The operation can be targeted at individual directories or recursively applied to subdirectories as well. 13 | 14 | By default, both Inbound and Outbound connections will be affected, but the scope can be controlled via the -Inbound or -Outbound switches. 15 | 16 | Special care should be taken when using this script due to its potentially broad impact. Blocking EXEs indiscriminately may disrupt applications depending on these executables. 17 | 18 | # Installing 19 | 20 | You can either download the PS1 script from here, or install using... 21 | 22 | ```powershell 23 | Install-Script BlockFolderWindowsFirewall -Force 24 | ``` 25 | 26 | Answer **Yes** to any prompts. `-Force` is optional, but it will force the script to update if it is outdated. 27 | 28 | This script is published on [PowerShell Gallery](https://www.powershellgallery.com/packages/BlockFolderWindowsFirewall). 29 | 30 | # Usage 31 | 32 | ```powershell 33 | BlockFolderWindowsFirewall [-Path ] [-Outbound] [-Inbound] [-Recurse] [-UnblockInstead] [-Version] [-Help] [-CheckForUpdate] 34 | ``` 35 | 36 | # Parameters 37 | 38 | | Parameter | Required | Description | 39 | | ----------------- | -------- | ---------------------------------------------------------------------- | 40 | | `-Path` | Yes | The folder of EXEs to block/unblock. | 41 | | `-Recurse` | No | Scans the folder and subfolders for EXEs. | 42 | | `-UnblockInstead` | No | Unblocks the EXEs in a folder or subfolder. | 43 | | `-Inbound` | No | Blocks all inbound connections for the EXEs in a folder or subfolder. | 44 | | `-Outbound` | No | Blocks all outbound connections for the EXEs in a folder or subfolder. | 45 | | `-CheckForUpdate` | No | Checks if there is an update available for the script. | 46 | | `-UpdateSelf` | No | Updates the script to the latest version. | 47 | | `-Help` | No | Displays the help message. | 48 | | `-Version` | No | Shows the current version of the script. | 49 | 50 | # Examples 51 | 52 | | Description | Command | 53 | | -------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | 54 | | Block all EXEs in a specified folder | `BlockFolderWindowsFirewall -Path "C:\Folder\Subfolder"` | 55 | | Block all EXEs in a specified folder and its subfolders | `BlockFolderWindowsFirewall -Path "C:\Folder\Subfolder" -Recurse` | 56 | | Block only the inbound connections for EXEs in a specified folder | `BlockFolderWindowsFirewall -Path "C:\Folder\Subfolder" -Inbound` | 57 | | Block only the outbound connections for EXEs in a specified folder | `BlockFolderWindowsFirewall -Path "C:\Folder\Subfolder" -Outbound` | 58 | | Unblock all EXEs in a specified folder | `BlockFolderWindowsFirewall -Path "C:\Folder\Subfolder" -UnblockInstead` | 59 | | Unblock all EXEs in a specified folder and its subfolders | `BlockFolderWindowsFirewall -Path "C:\Folder\Subfolder" -Recurse -UnblockInstead` | 60 | | Unblock only the inbound connections for EXEs in a specified folder | `BlockFolderWindowsFirewall -Path "C:\Folder\Subfolder" -UnblockInstead -Inbound` | 61 | | Unblock only the outbound connections for EXEs in a specified folder | `BlockFolderWindowsFirewall -Path "C:\Folder\Subfolder" -UnblockInstead -Outbound` | 62 | | Display help for the script | `BlockFolderWindowsFirewall -Help` | 63 | | Check the current version of the script | `BlockFolderWindowsFirewall -Version` | 64 | | Check if there is an update available for the script | `BlockFolderWindowsFirewall -CheckForUpdate` | 65 | 66 | # Screenshot 67 | 68 | ![Screenshot](https://github.com/asheroto/BlockFolderWindowsFirewall/assets/49938263/439d99ed-0ad1-4f75-87bc-11d385185567) -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | UPDATE-NOTES 2 | dist/ -------------------------------------------------------------------------------- /BlockFolderWindowsFirewall.ps1: -------------------------------------------------------------------------------- 1 | <#PSScriptInfo 2 | 3 | .VERSION 1.0.2 4 | 5 | .GUID c7a7f36d-3d4f-4e2e-9bec-336ec8a0eb16 6 | 7 | .AUTHOR asherto 8 | 9 | .COMPANYNAME asheroto 10 | 11 | .TAGS PowerShell Windows exe block firewall folder directory recursive 12 | 13 | .PROJECTURI https://github.com/asheroto/BlockFolderWindowsFirewall 14 | 15 | .RELEASENOTES 16 | [Version 0.0.1] - Initial Release. 17 | [Version 0.0.2] - Added recurse option. 18 | [Version 0.0.3] - Updated code signing certificate. 19 | [Version 1.0.0] - Major improvements. Added -Version, -Help, -CheckForUpdate. Added inbound/outbound option (will do both if not specified). 20 | [Version 1.0.1] - Added additional line breaks, changed first line to warning, and added PowerShell gallery info to -CheckForUpdate 21 | [Version 1.0.2] - Added UpdateSelf function, fixed CheckForUpdate function. 22 | 23 | #> 24 | 25 | <# 26 | .SYNOPSIS 27 | Block all EXEs in a specified folder in Windows Firewall. 28 | .DESCRIPTION 29 | This script provides functionalities to manage (block/unblock) executables (EXEs) in specified directories via Windows Firewall. The operation can be targeted at individual directories or recursively applied to subdirectories as well. 30 | 31 | By default, both Inbound and Outbound connections will be affected, but the scope can be controlled via the -Inbound or -Outbound switches. 32 | 33 | Here are key switches to guide the script's behavior: 34 | -Path to specify the target directory. 35 | -Recurse switch will include all subdirectories in the operation. 36 | -UnblockInstead switch changes the operation mode from blocking to unblocking. 37 | -Inbound switch will only affect Inbound connections. 38 | -Outbound switch will only affect Outbound connections. 39 | 40 | Additional utilities include: 41 | -Version switch displays the current version of the script. 42 | -Help switch brings up the help information for the script usage. 43 | -CheckForUpdate switch verifies if the current script version is up-to-date. 44 | 45 | Special care should be taken when using this script due to its potentially broad impact. Blocking EXEs indiscriminately may disrupt applications depending on these executables. 46 | 47 | For detailed examples of usage, refer to the .EXAMPLE section. 48 | .EXAMPLE 49 | BlockFolderWindowsFirewall -Path "C:\Folder\Subfolder" 50 | This command will block both inbound and outbound traffic for all EXEs in the specified folder. 51 | .EXAMPLE 52 | BlockFolderWindowsFirewall -Path "C:\Folder\Subfolder" -Recurse 53 | This command will block both inbound and outbound traffic for all EXEs in the specified folder and all its subfolders. 54 | .EXAMPLE 55 | BlockFolderWindowsFirewall -Path "C:\Folder\Subfolder" -Inbound 56 | This command will block only inbound traffic for all EXEs in the specified folder. 57 | .EXAMPLE 58 | BlockFolderWindowsFirewall -Path "C:\Folder\Subfolder" -UnblockInstead 59 | This command will unblock both inbound and outbound traffic for all EXEs in the specified folder. 60 | .EXAMPLE 61 | BlockFolderWindowsFirewall -Path "C:\Folder\Subfolder" -Recurse -UnblockInstead 62 | This command will unblock both inbound and outbound traffic for all EXEs in the specified folder and all its subfolders. 63 | .EXAMPLE 64 | BlockFolderWindowsFirewall -Path "C:\Folder\Subfolder" -Outbound -UnblockInstead 65 | This command will unblock only outbound traffic for all EXEs in the specified folder. 66 | .PARAMETER Path 67 | The directory path to target for the operation. 68 | .PARAMETER Recurse 69 | Include all subdirectories in the operation. 70 | .PARAMETER UnblockInstead 71 | Change the operation mode from blocking to unblocking. 72 | .PARAMETER Inbound 73 | Only affect Inbound connections. 74 | .PARAMETER Outbound 75 | Only affect Outbound connections. 76 | .PARAMETER CheckForUpdate 77 | Verify if the current script version is up-to-date. 78 | .PARAMETER UpdateSelf 79 | Updates the script to the latest version on PSGallery. 80 | .PARAMETER Version 81 | Display the current version of the script. 82 | .PARAMETER Help 83 | Bring up the help information for the script usage. 84 | .NOTES 85 | Version : 1.0.2 86 | Created by : asheroto 87 | .LINK 88 | Project Site: https://github.com/asheroto/BlockFolderWindowsFirewall 89 | #> 90 | 91 | #Requires -RunAsAdministrator 92 | 93 | [CmdletBinding()] 94 | param ( 95 | [String]$Path, 96 | [Switch]$Outbound, 97 | [Switch]$Inbound, 98 | [Switch]$Recurse, 99 | [Switch]$UnblockInstead, 100 | [switch]$CheckForUpdate, 101 | [switch]$UpdateSelf, 102 | [switch]$Version, 103 | [switch]$Help 104 | ) 105 | 106 | # Version 107 | $CurrentVersion = '1.0.2' 108 | $RepoOwner = 'asheroto' 109 | $RepoName = 'BlockFolderWindowsFirewall' 110 | $PowerShellGalleryName = 'BlockFolderWindowsFirewall' 111 | 112 | # Display version if -Version is specified 113 | if ($Version.IsPresent) { 114 | $CurrentVersion 115 | exit 0 116 | } 117 | 118 | # Help 119 | if ($Help) { 120 | Get-Help -Name $MyInvocation.MyCommand.Source -Full 121 | exit 0 122 | } 123 | 124 | function Get-GitHubRelease { 125 | <# 126 | .SYNOPSIS 127 | Fetches the latest release information of a GitHub repository. 128 | 129 | .DESCRIPTION 130 | This function uses the GitHub API to get information about the latest release of a specified repository, including its version and the date it was published. 131 | 132 | .PARAMETER Owner 133 | The GitHub username of the repository owner. 134 | 135 | .PARAMETER Repo 136 | The name of the repository. 137 | 138 | .EXAMPLE 139 | Get-GitHubRelease -Owner "asheroto" -Repo "winget-install" 140 | This command retrieves the latest release version and published datetime of the winget-install repository owned by asheroto. 141 | #> 142 | [CmdletBinding()] 143 | param ( 144 | [string]$Owner, 145 | [string]$Repo 146 | ) 147 | try { 148 | $url = "https://api.github.com/repos/$Owner/$Repo/releases/latest" 149 | $response = Invoke-RestMethod -Uri $url -ErrorAction Stop 150 | 151 | $latestVersion = $response.tag_name 152 | $publishedAt = $response.published_at 153 | 154 | # Convert UTC time string to local time 155 | $UtcDateTime = [DateTime]::Parse($publishedAt, [System.Globalization.CultureInfo]::InvariantCulture, [System.Globalization.DateTimeStyles]::RoundtripKind) 156 | $PublishedLocalDateTime = $UtcDateTime.ToLocalTime() 157 | 158 | [PSCustomObject]@{ 159 | LatestVersion = $latestVersion 160 | PublishedDateTime = $PublishedLocalDateTime 161 | } 162 | } catch { 163 | Write-Error "Unable to check for updates.`nError: $_" 164 | exit 1 165 | } 166 | } 167 | 168 | function CheckForUpdate { 169 | param ( 170 | [string]$RepoOwner, 171 | [string]$RepoName, 172 | [version]$CurrentVersion, 173 | [string]$PowerShellGalleryName 174 | ) 175 | 176 | $Data = Get-GitHubRelease -Owner $RepoOwner -Repo $RepoName 177 | 178 | Write-Output "" 179 | Write-Output ("Repository: {0,-40}" -f "https://github.com/$RepoOwner/$RepoName") 180 | Write-Output ("Current Version: {0,-40}" -f $CurrentVersion) 181 | Write-Output ("Latest Version: {0,-40}" -f $Data.LatestVersion) 182 | Write-Output ("Published at: {0,-40}" -f $Data.PublishedDateTime) 183 | 184 | if ($Data.LatestVersion -gt $CurrentVersion) { 185 | Write-Output ("Status: {0,-40}" -f "A new version is available.") 186 | Write-Output "`nOptions to update:" 187 | Write-Output "- Download latest release: https://github.com/$RepoOwner/$RepoName/releases" 188 | if ($PowerShellGalleryName) { 189 | Write-Output "- Run: $RepoName -UpdateSelf" 190 | Write-Output "- Run: Install-Script $PowerShellGalleryName -Force" 191 | } 192 | } else { 193 | Write-Output ("Status: {0,-40}" -f "Up to date.") 194 | } 195 | exit 0 196 | } 197 | 198 | function UpdateSelf { 199 | try { 200 | # Get PSGallery version of script 201 | $psGalleryScriptVersion = (Find-Script -Name $PowerShellGalleryName).Version 202 | 203 | # If the current version is less than the PSGallery version, update the script 204 | if ($CurrentVersion -lt $psGalleryScriptVersion) { 205 | Write-Output "Updating script to version $psGalleryScriptVersion..." 206 | 207 | # Install NuGet PackageProvider if not already installed 208 | if (-not (Get-PackageProvider -Name NuGet -ErrorAction SilentlyContinue)) { 209 | Install-PackageProvider -Name "NuGet" -Force 210 | } 211 | 212 | # Trust the PSGallery if not already trusted 213 | $psRepoInstallationPolicy = (Get-PSRepository -Name 'PSGallery').InstallationPolicy 214 | if ($psRepoInstallationPolicy -ne 'Trusted') { 215 | Set-PSRepository -Name 'PSGallery' -InstallationPolicy Trusted | Out-Null 216 | } 217 | 218 | # Update the script 219 | Install-Script $PowerShellGalleryName -Force 220 | 221 | # If PSGallery was not trusted, reset it to its original state 222 | if ($psRepoInstallationPolicy -ne 'Trusted') { 223 | Set-PSRepository -Name 'PSGallery' -InstallationPolicy $psRepoInstallationPolicy | Out-Null 224 | } 225 | 226 | Write-Output "Script updated to version $psGalleryScriptVersion." 227 | exit 0 228 | } else { 229 | Write-Output "Script is already up to date." 230 | exit 0 231 | } 232 | } catch { 233 | Write-Output "An error occurred: $_" 234 | exit 1 235 | } 236 | } 237 | 238 | function Block-Exe { 239 | param( 240 | [String]$FileName, 241 | [String]$FilePath, 242 | [Switch]$Inbound, 243 | [Switch]$Outbound 244 | ) 245 | 246 | If ($Inbound.IsPresent -eq $false -and $Outbound.IsPresent -eq $false) { 247 | Write-Output "Blocking Inbound and Outbound $FilePath..." 248 | New-NetFirewallRule -DisplayName "$FileName" -Direction Inbound -Program $FilePath -Action Block | Out-Null 249 | New-NetFirewallRule -DisplayName "$FileName" -Direction Outbound -Program $FilePath -Action Block | Out-Null 250 | } elseif ($Inbound.IsPresent) { 251 | Write-Output "Blocking Inbound $FilePath..." 252 | New-NetFirewallRule -DisplayName "$FileName" -Direction Inbound -Program $FilePath -Action Block | Out-Null 253 | } elseif ($Outbound.IsPresent) { 254 | Write-Output "Blocking Outbound $FilePath..." 255 | New-NetFirewallRule -DisplayName "$FileName" -Direction Outbound -Program $FilePath -Action Block | Out-Null 256 | } 257 | } 258 | 259 | function Unblock-Exe { 260 | param( 261 | [String]$FilePath, 262 | [Switch]$Inbound, 263 | [Switch]$Outbound 264 | ) 265 | 266 | if ($Inbound.IsPresent -eq $false -and $Outbound.IsPresent -eq $false) { 267 | Write-Output "Unblocking Inbound and Outbound $FilePath..." 268 | $matchingRules = Get-NetFirewallApplicationFilter | ? { $_.AppPath -eq "$FilePath" } | % { Get-NetFirewallRule $_.InstanceID } 269 | if ($matchingRules) { 270 | $matchingRules | Remove-NetFirewallRule 271 | } else { 272 | Write-Warning "No matching Inbound and Outbound rules found for $FilePath" 273 | } 274 | } elseif ($Inbound.IsPresent) { 275 | Write-Output "Unblocking Inbound $FilePath..." 276 | $matchingRules = Get-NetFirewallApplicationFilter | ? { $_.AppPath -eq "$FilePath" } | % { Get-NetFirewallRule $_.InstanceID | ? { $_.Direction -eq "Inbound" } } 277 | if ($matchingRules) { 278 | $matchingRules | Remove-NetFirewallRule 279 | } else { 280 | Write-Warning "No matching Inbound rules found for $FilePath" 281 | } 282 | } elseif ($Outbound.IsPresent) { 283 | Write-Output "Unblocking Outbound $FilePath..." 284 | $matchingRules = Get-NetFirewallApplicationFilter | ? { $_.AppPath -eq "$FilePath" } | % { Get-NetFirewallRule $_.InstanceID | ? { $_.Direction -eq "Outbound" } } 285 | if ($matchingRules) { 286 | $matchingRules | Remove-NetFirewallRule 287 | } else { 288 | Write-Warning "No matching Outbound rules found for $FilePath" 289 | } 290 | } 291 | } 292 | 293 | # Update the script if -UpdateSelf is specified 294 | if ($UpdateSelf) { UpdateSelf } 295 | 296 | # Check for updates if -CheckForUpdate is specified 297 | if ($CheckForUpdate) { CheckForUpdate -RepoOwner $RepoOwner -RepoName $RepoName -CurrentVersion $CurrentVersion -PowerShellGalleryName $PowerShellGalleryName } 298 | 299 | # If Path is not set, check if -Version, -Help, or -CheckForUpdate is specified 300 | if ("" -eq $Path) { 301 | if ($Version.IsPresent -or $Help.IsPresent -or $CheckForUpdate.IsPresent) { 302 | # Do nothing 303 | } else { 304 | Write-Error "-Path is required" 305 | exit 1 306 | } 307 | } 308 | 309 | # If -Recurse or -UnblockInstead is specified, -Path is required 310 | if ($Recurse.IsPresent -or $UnblockInstead.IsPresent -or $Outbound.IsPresent -or $Inbound.IsPresent) { 311 | if ("" -eq $Path) { 312 | Write-Error "-Path is required" 313 | exit 1 314 | } 315 | } 316 | 317 | # Confirm folder path exists 318 | if (Test-Path -Path $Path -PathType Container) { 319 | # Update note 320 | Write-Output "`n$RepoName $CurrentVersion" 321 | Write-Output "To check for updates, run $RepoName -CheckForUpdate`n" 322 | 323 | # Folder path exists 324 | Write-Output "Folder exists, continuing...`n" 325 | 326 | # Pause for 10 seconds if the folder is C:\ 327 | If ($Path -eq "C:\") { 328 | Write-Output "WARNING: You specified C:\ as the path, this will block all EXEs on the C drive. Press CTRL+C to cancel, or wait 10 seconds to continue..." 329 | Start-Sleep -Seconds 10 330 | } 331 | 332 | # Determine if we're blocking or unblocking 333 | if ($UnblockInstead) { 334 | # Unblocking 335 | if ($Recurse) { 336 | # Recursively unblocking 337 | Write-Output "Recursively unblocking EXEs in $Path..." 338 | Get-ChildItem -Path $Path -Filter "*.exe" -Recurse | ForEach-Object { 339 | $FilePath = $_.FullName 340 | $FileName = Split-Path $FilePath -Leaf 341 | Unblock-Exe -FilePath $FilePath -FileName $FileName -Inbound:$Inbound.IsPresent -Outbound:$Outbound.IsPresent 342 | } 343 | } else { 344 | # Not recursively unblocking 345 | Write-Output "Unblocking EXEs in $Path..." 346 | Get-ChildItem -Path $Path -Filter "*.exe" | ForEach-Object { 347 | $FilePath = $_.FullName 348 | $FileName = Split-Path $FilePath -Leaf 349 | Unblock-Exe -FilePath $FilePath -FileName $FileName -Inbound:$Inbound.IsPresent -Outbound:$Outbound.IsPresent 350 | } 351 | } 352 | } else { 353 | # Blocking 354 | if ($Recurse) { 355 | # Recursively blocking 356 | Write-Output "Recursively blocking EXEs in $Path..." 357 | Get-ChildItem -Path $Path -Filter "*.exe" -Recurse | ForEach-Object { 358 | $FilePath = $_.FullName 359 | $FileName = Split-Path $FilePath -Leaf 360 | Block-Exe -FilePath $FilePath -FileName $FileName -Inbound:$Inbound.IsPresent -Outbound:$Outbound.IsPresent 361 | } 362 | } else { 363 | # Not recursively blocking 364 | Write-Output "Blocking EXEs in $Path..." 365 | Get-ChildItem -Path $Path -Filter "*.exe" | ForEach-Object { 366 | $FilePath = $_.FullName 367 | $FileName = Split-Path $FilePath -Leaf 368 | Block-Exe -FilePath $FilePath -FileName $FileName -Inbound:$Inbound.IsPresent -Outbound:$Outbound.IsPresent 369 | } 370 | } 371 | } 372 | 373 | Write-Output "Done!" 374 | } else { 375 | # Folder path does not exist 376 | Write-Output "Folder does NOT exist, please run script again with a valid path" 377 | } 378 | 379 | Write-Output "" --------------------------------------------------------------------------------