How to Configure AppLocker on Windows Server 2025
AppLocker is a Windows application control feature that restricts which executables, scripts, installers, DLLs, and packaged apps can run on a system. Introduced in Windows 7 and Windows Server 2008 R2, AppLocker has been refined across every subsequent Windows Server version and remains a useful control for environments that need granular user-space application whitelisting without the kernel-level complexity of Windows Defender Application Control (WDAC). On Windows Server 2025, AppLocker integrates with Group Policy, supports digital signature-based publisher rules, and writes detailed event log entries that make both enforcement and auditing straightforward. This guide covers the full AppLocker configuration workflow: rule types, creation through Group Policy, publisher and path rules, audit mode, event log analysis, and a comparison with WDAC to help you choose the right tool for your environment.
Prerequisites
- Windows Server 2025 (Standard or Datacenter) — Desktop Experience recommended for GPMC and secpol.msc access
- Local Administrator or Domain Administrator privileges
- The Application Identity service (
AppIDSvc) must be running for AppLocker to enforce rules - Group Policy Management Console (GPMC) installed for domain-wide deployment
- Understanding that AppLocker rules apply to non-administrator users by default; administrators can run any software unless explicitly restricted
- A test OU or test server to validate rules before production deployment
Step 1: Start the Application Identity Service
AppLocker depends entirely on the Application Identity service (AppIDSvc). If this service is not running, AppLocker will not enforce any rules — even if policies are correctly configured. Configure it to start automatically on all servers where AppLocker will be enforced.
# Check the current state of the Application Identity service
Get-Service -Name AppIDSvc | Select-Object Name, Status, StartType
# Set startup type to Automatic and start the service
Set-Service -Name AppIDSvc -StartupType Automatic
Start-Service -Name AppIDSvc
# Verify it is running
(Get-Service -Name AppIDSvc).Status -eq "Running"
# If deploying via Group Policy, configure the service startup through:
# Computer Config → Windows Settings → Security Settings → System Services → Application Identity
# Set to: Automatic
# On multiple servers via PowerShell remoting
$servers = @("SRV-APP01", "SRV-APP02", "SRV-WEB01")
Invoke-Command -ComputerName $servers -ScriptBlock {
Set-Service -Name AppIDSvc -StartupType Automatic
Start-Service -Name AppIDSvc
[PSCustomObject]@{
Server = $env:COMPUTERNAME
Status = (Get-Service -Name AppIDSvc).Status
}
}
Step 2: Understand AppLocker Rule Types
AppLocker organizes rules into five rule collections, each targeting a different type of code. Understanding which collection to use is essential before creating your first policy.
- Executable Rules — Controls
.exeand.comfiles - Windows Installer Rules — Controls
.msi,.msp, and.mstinstaller packages - Script Rules — Controls
.ps1,.bat,.cmd,.vbs, and.jsscripts - DLL Rules — Controls
.dlland.ocxfiles (use with caution — significant performance impact) - Packaged App Rules — Controls UWP / Microsoft Store apps by publisher and name
# View existing AppLocker policy on the local machine
Get-AppLockerPolicy -Effective | Format-List
# View AppLocker policy from a specific GPO (requires GPMC RSAT tools)
Get-AppLockerPolicy -Ldap "LDAP://CN={GPO-GUID},CN=Policies,CN=System,DC=contoso,DC=com" |
Format-List
# Get a summary of rules by type
$policy = Get-AppLockerPolicy -Effective
$policy.RuleCollections | ForEach-Object {
[PSCustomObject]@{
RuleCollection = $_.RuleCollectionType
EnforcementMode = $_.EnforcementMode
RuleCount = $_.Count
}
} | Format-Table
Step 3: Automatically Generate Default Rules
Before creating custom rules, generate the default AppLocker rules using the Automatically Generate Rules wizard or PowerShell. The default rules allow everyone to run anything from %SystemRoot% (Windows folder) and %ProgramFiles%, and allow administrators to run everything. These defaults prevent locking out users from critical system binaries.
# Create default rules for Executable, Script, and Installer collections via PowerShell
# These rules mirror what the "Automatically Generate Rules" wizard creates
# Default rule: Allow Everyone to run from Program Files
New-AppLockerPolicy -RuleType Publisher, Path, Hash `
-User "Everyone" `
-FileInformation (Get-AppLockerFileInformation -Directory "C:Program Files" -Recurse) |
Set-AppLockerPolicy -Merge
# Default rule: Allow Everyone to run from Windows folder
New-AppLockerPolicy -RuleType Publisher, Path, Hash `
-User "Everyone" `
-FileInformation (Get-AppLockerFileInformation -Directory "C:Windows" -Recurse) |
Set-AppLockerPolicy -Merge
Write-Host "Default AppLocker rules created"
# Alternatively, use the Group Policy editor (secpol.msc or GPMC):
# Security Settings → Application Control Policies → AppLocker →
# Right-click "Executable Rules" → Create Default Rules
Step 4: Create Publisher (Signer) Rules
Publisher rules are the most maintainable rule type. They allow all files signed by a specific publisher certificate to run, meaning the rule remains valid as software updates are released without requiring rule updates. This is the recommended rule type for commercial software.
# Create a publisher rule for a signed executable
$exePath = "C:Program FilesGoogleChromeApplicationchrome.exe"
# Extract file information for rule creation
$fileInfo = Get-AppLockerFileInformation -Path $exePath
# Create a publisher-based policy rule
$publisherRule = New-AppLockerPolicy -FileInformation $fileInfo `
-RuleType Publisher `
-User "Everyone" `
-RuleNamePrefix "Allow_Chrome"
# Review the generated rule
$publisherRule.RuleCollections | Format-List
# Merge the rule into the effective local policy
$publisherRule | Set-AppLockerPolicy -Merge
# Create a publisher rule for multiple files in a directory
$softwareDir = "C:Program FilesYourApp"
$fileInfoBatch = Get-AppLockerFileInformation -Directory $softwareDir -Recurse
$batchPolicy = New-AppLockerPolicy -FileInformation $fileInfoBatch `
-RuleType Publisher `
-User "Domain Users" `
-RuleNamePrefix "Allow_YourApp"
$batchPolicy | Set-AppLockerPolicy -Merge
Step 5: Create Path Rules
Path rules allow execution of any file from a specified directory path, regardless of publisher or hash. They are simpler but less precise than publisher rules — if a user can write files to the allowed path, they can potentially bypass the rule by placing malicious executables there. Always combine path rules with NTFS permissions to prevent non-administrator writes to allowed paths.
# Create a path rule allowing execution from a specific custom directory
$xmlRule = @"
<AppLockerPolicy Version="1">
<RuleCollection Type="Exe" EnforcementMode="AuditOnly">
<PathRule Id="{$(New-Guid)}" Name="Allow D:ApprovedApps" Description="Approved internal apps" `
UserOrGroupSid="S-1-1-0" Action="Allow">
<Conditions>
<PathCondition Path="D:ApprovedApps*" />
</Conditions>
</PathRule>
</RuleCollection>
</AppLockerPolicy>
"@
$xmlRule | Set-AppLockerPolicy -Merge -ErrorAction Stop
# Alternatively, create path rules using PowerShell file information
$pathPolicy = New-AppLockerPolicy `
-FileInformation (Get-AppLockerFileInformation -Path "D:ApprovedApps*") `
-RuleType Path `
-User "Domain Users" `
-RuleNamePrefix "Allow_ApprovedApps_Path"
$pathPolicy | Set-AppLockerPolicy -Merge
Step 6: Create File Hash Rules
Hash rules allow a specific version of a file to run, identified by its cryptographic hash. They are the most precise rule type but require updating every time a file changes (such as after a software update). Use hash rules as a last resort for unsigned legacy software that cannot be whitelisted by publisher or path.
# Create hash rules for specific unsigned executables
$legacyApps = @(
"C:LegacyApplegacy_tool.exe",
"C:LegacyApphelper_util.exe"
)
foreach ($app in $legacyApps) {
$fileInfo = Get-AppLockerFileInformation -Path $app
$hashPolicy = New-AppLockerPolicy -FileInformation $fileInfo `
-RuleType Hash `
-User "Everyone" `
-RuleNamePrefix "Allow_Hash_$(Split-Path $app -Leaf)"
$hashPolicy | Set-AppLockerPolicy -Merge
Write-Host "Hash rule created for: $(Split-Path $app -Leaf)"
}
# List all hash rules currently in policy
(Get-AppLockerPolicy -Effective).RuleCollections |
ForEach-Object { $_.Rules } |
Where-Object { $_.GetType().Name -eq "FileHashRule" } |
Select-Object Name, Action, UserOrGroupSid
Step 7: Configure Enforcement Mode — Audit vs. Enforce
Each AppLocker rule collection has an independent enforcement mode. Audit Only mode logs events without blocking; Enforce Rules mode actively blocks non-matching code. Always start in Audit mode, monitor logs for at least one to two weeks, then graduate to enforcement.
# Export current policy to XML for editing
Get-AppLockerPolicy -Effective -Xml | Out-File "C:AppLockerCurrentPolicy.xml"
# Edit the XML to change enforcement mode per collection
# Change EnforcementMode="AuditOnly" to EnforcementMode="Enabled" for each collection
# Quick mode change using PowerShell (Audit → Enforce for Executable rules)
$policyXml = [xml](Get-Content "C:AppLockerCurrentPolicy.xml")
$policyXml.AppLockerPolicy.RuleCollection |
Where-Object { $_.Type -eq "Exe" } |
ForEach-Object { $_.EnforcementMode = "Enabled" }
$policyXml.Save("C:AppLockerEnforcedPolicy.xml")
# Apply the modified policy
Set-AppLockerPolicy -XmlPolicy "C:AppLockerEnforcedPolicy.xml"
# Confirm current enforcement mode per collection
(Get-AppLockerPolicy -Effective).RuleCollections |
Select-Object RuleCollectionType, EnforcementMode | Format-Table
Step 8: Deploy AppLocker Policy via Group Policy
For domain-wide enforcement, configure AppLocker through a Group Policy Object linked to the target OU. This ensures all servers in the OU receive consistent rules and the Application Identity service is started automatically.
# Export the tested and refined local AppLocker policy to XML
Get-AppLockerPolicy -Effective -Xml | Out-File "C:AppLockerProductionPolicy.xml"
# Import the policy into a Group Policy Object
# The target GPO must already exist — create it in GPMC first
$gpoName = "AppLocker - Server Application Control"
$targetOU = "OU=Servers,DC=contoso,DC=com"
# Create and link the GPO
New-GPO -Name $gpoName | New-GPLink -Target $targetOU
# Apply the AppLocker XML policy to the GPO via PowerShell
# Note: Set-AppLockerPolicy can target GPOs by LDAP path
$gpoLdapPath = (Get-GPO -Name $gpoName).Path
Set-AppLockerPolicy -XmlPolicy "C:AppLockerProductionPolicy.xml" `
-Ldap $gpoLdapPath
# Force policy refresh on a test server
Invoke-Command -ComputerName "SRV-TEST01" -ScriptBlock { gpupdate /force }
# Verify the policy applied on the test server
Invoke-Command -ComputerName "SRV-TEST01" -ScriptBlock {
Get-AppLockerPolicy -Effective | Format-List
}
Step 9: Analyze AppLocker Event Logs
AppLocker writes events to dedicated event logs under Applications and Services Logs → Microsoft → Windows → AppLocker. Understanding the key Event IDs allows rapid diagnosis of both blocked users and potential policy gaps.
# AppLocker Event IDs:
# 8003 — EXE/DLL was allowed to run (Audit Mode — would not have been blocked)
# 8004 — EXE/DLL was BLOCKED (Enforce Mode) or would have been blocked (Audit Mode)
# 8005 — Script was allowed to run (Audit Mode)
# 8006 — Script was BLOCKED (Enforce Mode) or would have been blocked (Audit Mode)
# 8007 — MSI/MSP was BLOCKED (Enforce Mode) or would have been blocked (Audit Mode)
# 8020 — Packaged app was allowed
# 8021 — Packaged app was BLOCKED or would have been blocked
# Query all block events across all AppLocker logs
$applockerLogs = @(
"Microsoft-Windows-AppLocker/EXE and DLL",
"Microsoft-Windows-AppLocker/MSI and Script",
"Microsoft-Windows-AppLocker/Packaged app-Deployment",
"Microsoft-Windows-AppLocker/Packaged app-Execution"
)
$blockEventIds = @(8004, 8006, 8007, 8021)
foreach ($log in $applockerLogs) {
try {
$events = Get-WinEvent -LogName $log -ErrorAction Stop |
Where-Object { $_.Id -in $blockEventIds } |
Select-Object TimeCreated, Id, Message
if ($events) {
Write-Host "`n=== $log ===" -ForegroundColor Yellow
$events | Sort-Object TimeCreated -Descending | Select-Object -First 20 |
Format-Table TimeCreated, Id, @{L="File";E={
if ($_.Message -match "File Name:s+(.+?)r") { $Matches[1] }
}}
}
} catch {
# Log may not exist if the rule collection has never run
}
}
# Summarize most frequently blocked files (useful for finding policy gaps)
Get-WinEvent -LogName "Microsoft-Windows-AppLocker/EXE and DLL" -ErrorAction SilentlyContinue |
Where-Object { $_.Id -eq 8004 } |
ForEach-Object {
if ($_.Message -match "File Name:s+(.+?)r") { $Matches[1].Trim() }
} | Group-Object | Sort-Object Count -Descending | Select-Object -First 20 |
Format-Table Count, Name
Step 10: AppLocker vs. WDAC — Choosing the Right Tool
Windows Server 2025 includes both AppLocker and WDAC. Understanding when to use each prevents confusion and ensures you select the control that best fits your security requirements.
- AppLocker — Best for user-space application control with GPO-based management, granular per-user or per-group rules, and environments where IT staff are comfortable with traditional rule-based whitelisting. Cannot control kernel drivers. Manageable via PowerShell and GPMC without specialized expertise.
- WDAC — Best for kernel and driver control, Virtualization-Based Security integration, and environments requiring the highest level of tamper resistance. WDAC policies apply to all users including administrators. More complex to create and update, but significantly more powerful.
- Software Restriction Policies (SRP) — The predecessor to AppLocker, now deprecated. Microsoft recommends migrating all SRP configurations to AppLocker or WDAC on Windows Server 2025.
# Check whether SRP (Software Restriction Policies) is configured (legacy check)
$srpPath = "HKLM:SOFTWAREPoliciesMicrosoftWindowsSafer"
if (Test-Path $srpPath) {
Write-Warning "Software Restriction Policies detected — consider migrating to AppLocker or WDAC"
Get-ItemProperty -Path $srpPath
} else {
Write-Host "No SRP policies found — environment is using AppLocker or WDAC (correct for WS2025)"
}
# Determine if WDAC is active alongside AppLocker
$ciActive = Test-Path "$env:SystemRootSystem32CodeIntegrityCiPoliciesActive"
Write-Host "WDAC policy active: $ciActive"
Write-Host "AppLocker enforcement mode:"
(Get-AppLockerPolicy -Effective).RuleCollections |
Select-Object RuleCollectionType, EnforcementMode | Format-Table
Conclusion
AppLocker on Windows Server 2025 gives administrators a structured, Group Policy-integrated framework for controlling which user-space applications, scripts, and installers are permitted to execute on server systems. By starting with default rules to protect system binaries, building publisher-based rules for maintainability, layering path and hash rules where needed for legacy software, and always beginning in Audit Mode before moving to enforcement, you build a robust application control posture without disrupting legitimate workloads. Regular review of the AppLocker event logs — especially Event IDs 8004 and 8006 — surfaces both blocked legitimate software requiring policy additions and potential malicious execution attempts requiring investigation. For complete application control coverage including kernel drivers and Virtualization-Based Security integration, pair AppLocker with WDAC rather than choosing between them — the two controls are complementary on Windows Server 2025 and work best as a unified defense-in-depth strategy.