I was recently deploying an application that required Windows Firewall rules to be created for an executable that ran from each user’s AppData folder. The way I accomplished this was to use a combination of PowerShell scripts and the Windows Task Scheduler.
I created two PowerShell scripts for this solution. Create_Scheduled_Task.ps1 and Create_Firewall_Rules.ps1.
The Create_Scheduled_Task.ps1 script copies the Create_Firewall_Rules.ps1 script to a subfolder in C:\Users\Public and creates a scheduled task to run that script each time a user logs onto the computer. You will need to set the $appName, $scriptName, and $folderPath variables.
#Set variables =========================================================
$appName = "Example App"
$scriptName = "Create_Firewall_Rules.ps1"
$folderPath = "$Env:public\"
#=======================================================================
#Set paths
$scriptFolder = "$folderPath$appname"
$scriptFile = "$scriptFolder\$scriptName"
#Create the public app directory if it does not already exist
if (!(Test-Path -PathType Container "$scriptFolder")){
New-Item -ItemType Directory -Path "$scriptFolder"
}
#Copy the firewall rules script to the public app directory if it does not already exist
if (!(Test-Path "$scriptFile")){
Copy-Item "$PSScriptRoot\$scriptName" -Destination "$scriptFolder"
}
#Create a scheduled task to run the firewall rules script at user logon
$taskName = "Create $appName Firewall Rules"
$task = Get-ScheduledTask | Where-Object -Property TaskName -eq $taskName | Select-Object -ExpandProperty TaskName -ErrorAction SilentlyContinue
if (!($task)){
$action = New-ScheduledTaskAction -Execute 'Powershell.exe' `
-Argument "-ExecutionPolicy Bypass -File $scriptFile"
$trigger = New-ScheduledTaskTrigger -AtLogon
$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -ExecutionTimeLimit 00:05:00
Register-ScheduledTask -Action $action -Trigger $trigger -TaskName "$taskName" -User "System" -Settings $settings -Description "Creates firewall rules to allow $appName for all domain users."
}
The Create_Firewall_Rules.ps1 script finds all domain user profiles on the system and creates firewall rules for each profile that does not already have rules created. You will need to set the $domain, $appName, and $appDataPath variables.
#Set seach domain (Case Sensitive)
$domain = 'LAB'
#Set application name
$appName = "Example App"
#Set the AppData path to the executable
$appDataPath = "AppData\Local\Example App\App.exe"
#Find all user profiles matching the search domain
$profiles = 'Registry::HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\ProfileList\*'
$accounts = Get-ItemProperty -path $profiles
Foreach ($account in $accounts) {
$objUser = New-Object System.Security.Principal.SecurityIdentifier($account.PSChildName)
$objName = $objUser.Translate([System.Security.Principal.NTAccount])
$account.PSChildName = $objName.value
}
$users = $accounts | Where-Object {$_.PSChildName -like "*$domain*"} | Select-Object -ExpandProperty PSChildName
$users = $users.Replace("$domain\","")
#Create a firewall exception for each user profile found
Foreach ($user in $users) {
if (!(Get-NetFirewallRule -DisplayName "$appname $user" -ErrorAction SilentlyContinue)){
New-NetFirewallRule -DisplayName "$appName $user" -Direction Inbound -Protocol TCP -LocalPort Any -RemoteAddress Any -Program "C:\Users\$user\$appDataPath" -Action Allow
}
}
I deployed this script to devices using an application in Configuration Manager. The application calls the Create_Scheduled_Task.ps1 script. I used another PowerShell script for the detection method.
$taskName = "Create Example App Firewall Rules"
$task = Get-ScheduledTask | Where-Object -Property TaskName -eq $taskName | Select-Object -ExpandProperty TaskName
$file = Test-Path "C:\Users\Public\Example App\Create_Firewall_Rules.ps1"
if ($task -and $file){
Write-Host "Installed"
}