A customer informed us that some users were getting a black screen after logon and others could not open the start menu after they got past the black screen. The customer restarted the RDS host but the issue was not resolved.
When checking the event logs I noticed system events with ID 10001 like the one below

This led me to think there was an issue with Appx and came across some material that suggested repairing Cortana. Trying to run the suggested PowerShell command failed and upon reviewing the AppPackage Log as suggested by the failure error I noticed that the package did not install because of insufficient resources. The system had only 6GB out of 128GB ram used and CPU (8 Cores) were at 2%

Searching further, I found this technet forum post in which the cause and solution are discussed.
Basically, every time a user logs into the RDS server, a new set of firewall rules is created and are not removed when the users log off, but new ones are re-created when they login again. This appears to happen most when using User Profile Disks (UPD). You may notice at this time that when trying to open WWindows Defender Firewall with Advanced Security to view the rules, the window would take a very long time to appear and end up in a “Not Responding” state.
This was resolved in Windows Server 2016 and 2019 by installing a Windows update, link for 2016 and 2019, and manually applying a registry key.
The updates were already installed so we proceeded to add the registry key as per below using Regedit.
Add “DeleteUserAppContainersOnLogoff” (DWORD) in “HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy” and set it to 1.
We logged off and logged back in and the Start menu was working again. All the other users also reported that this resolved the issue.
At this stage it is suggested that the previously created firewall rules are also deleted. These are the registry keys were the rules are stored.
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\FirewallRules (Server 2016 and 2019)
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\\RestrictedServices\AppIso\FirewallRules (Server 2019 only)
Instead of deleting the whole set of entries, we decided on taking another path and use the PowerShell script provided by user Paul Boerefijn CCS which removes the firewall rules and keeps a set of unique rules. The process was going to take over 15hrs to remove 12,000 inbound rules and we don’t know how long it was going to take to remove the outbound rules. So instead we used a different script found on stackoverflow which rather than using the “Remove-NetFirewallRule” PowerShell command it removed the rules directly from within the registry with the “Remove-ItemProperty” command which sped up the process and all 30,000 rules were deleted in 1.5Hrs. The script used is available below with some minor additions
NOTE Make sure that you change the Rule2 deletion line to match the correct registry path depending on which windows server version you are running it on. These are indicated in the script
#Script thanks to user js2010
#source https://stackoverflow.com/a/40915201
#added registry paths notes
$profiles = get-wmiobject -class win32_userprofile
Write-Host "Getting Firewall Rules"
# deleting rules with no owner would be disastrous
$Rules = Get-NetFirewallRule -All |
Where-Object {$profiles.sid -notcontains $_.owner -and $_.owner }
Write-Host "Getting Firewall Rules from ConfigurableServiceStore Store"
$rules2 = Get-NetFirewallRule -All -PolicyStore ConfigurableServiceStore |
Where-Object { $profiles.sid -notcontains $_.owner -and $_.owner }
$total = $rules.count + $rules2.count
Write-Host "Deleting" $total "Firewall Rules:" -ForegroundColor Green
$result = measure-command {
# tracking
$start = Get-Date; $i = 0.0 ;
foreach($rule in $rules){
# action
remove-itemproperty -path "HKLM:\System\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\FirewallRules" -name $rule.name
# progress
$i = $i + 1.0
$prct = $i / $total * 100.0
$elapsed = (Get-Date) - $start;
$totaltime = ($elapsed.TotalSeconds) / ($prct / 100.0)
$remain = $totaltime - $elapsed.TotalSeconds
$eta = (Get-Date).AddSeconds($remain)
# display
$prctnice = [math]::round($prct,2)
$elapsednice = $([string]::Format("{0:d2}:{1:d2}:{2:d2}", $elapsed.hours, $elapsed.minutes, $elapsed.seconds))
$speed = $i/$elapsed.totalminutes
$speednice = [math]::round($speed,2)
Write-Progress -Activity "Deleting rules ETA $eta elapsed $elapsednice loops/min $speednice" -Status "$prctnice" -PercentComplete $prct -secondsremaining $remain
}
# tracking
# $start = Get-Date; $i = 0 ; $total = $rules2.Count
foreach($rule2 in $rules2) {
# action
#change path according to the Windows Server version used:
#Windows Server 2019 Path = "HKLM:\SYSTEM\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\RestrictedServices\AppIso\FirewallRules"
#Windows Server 2016 Path = "HKLM:\System\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\RestrictedServices\Configurable\System"
remove-itemproperty -path "HKLM:\System\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\RestrictedServices\Configurable\System" -name $rule2.name
# progress
$i = $i + 1.0
$prct = $i / $total * 100.0
$elapse = (Get-Date) - $start;
$totaltime = ($elapsed.TotalSeconds) / ($prct / 100.0)
$remain = $totaltime - $elapsed.TotalSeconds
$eta = (Get-Date).AddSeconds($remain)
# display
$prctnice = [math]::round($prct,2)
$elapsednice = $([string]::Format("{0:d2}:{1:d2}:{2:d2}", $elapsed.hours, $elapsed.minutes, $elapsed.seconds))
$speed = $i/$elapsed.totalminutes
$speednice = [math]::round($speed,2)
Write-Progress -Activity "Deleting rules2 ETA $eta elapsed $elapsednice loops/min $speednice" -Status "$prctnice" -PercentComplete $prct -secondsremaining $remain
}
}
$end = get-date
write-host end $end
write-host eta $eta
write-host $result.minutes min $result.seconds sec
Once the script completes, the rules are removed and you will notice that the Windows Defender Firewall with Advanced Security window would open normally.
Both scripts catered to avoid deleting the rules which had no owner set in the properties. Deleting these rules could case problems.
The purpose of this blog post is to try and consolidate all the information we found to resolve the issue. A big thanks goes to all the contributors in the different forums.
Hope you find it useful.
Hello. Thank a lot for your web site. I have the same issue on RDS ferme 2019 : long black screen on logon and start menu doe’nt work.
I apply script. Durring 3 hours and more 15000 registry entry delete. But after, I have still issue with start menu. Have you an idea ?
Hi,
in some cases I read that clearing the registry manually solved the issue.
Also make sure that you applied the registry fixes manually to prevent this from happening again.
thank you for your reply. gow to applied with “Windows Server 2019 Path” ? I change under “action” and after “remove-itemproperty -path” but script don’t delete entry and i have several thousand entry in “HKLM:\SYSTEM\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\RestrictedServices\AppIso\FirewallRules”.
thank you very much.
Hi
Just to prevent you from possible future harm: It’s my understanding that only changing the registry path for AppIso (rules2) with WinServer 2019 doesn’t do the trick.
According to Microsoft, the AppIso rules are not accessible to the Get-NetFirewallRule Cmdlet, which the LapuLapu / Paul Boerefijn script uses for counting the rules at the top and then deleting them further down in the loop.
We currently have a 2019 TS with severe registry bloat, since the DeleteUserAppContainersOnLogoff RegKey was not set initially. After running the LapuLapu script as we did in the past, followed by setting the RegKey, it failed to resolve the problem, on the contrary, it made matters worse. Logoff would take up to 30 minutes per user, leading to ghost sessions and an unresponsive system we had to reboot during the day. HKLM:SYSTEM hive was still huge.
We just now discovered the new AppIso path which was not supported in the original LapuLapu skript and in our case contains 300’000k entries. I’m now trying to change the skript accordingly, which lead me to your site. By simply changing the path, as you suggest, I can tell you first hand though, that the entries in AppIso remain unaffected.
BR
Hi Michael,
are you getting any errors when the script tries to delete the entries in AppIso\FirewallRules?
Just in case, are you running the script as admin to make sure you have permission to remove entries?
some people also delete the registry path completely and re-create it as in.
https://community.spiceworks.com/topic/2285411-server2019-rds-hundreds-of-firewall-rules-per-user-per-session
I am not suggesting you do this unless you export/backup the registry path.
Hope it helps.
Hello Brian
What I wanted to point out is this:
– The AppIso path under Server 2019 is indeed new, but it doesn’t completely replace the Configurable\System path. There is still some amount of bloat happening under the latter.
– Since the script gathers the rules2 array, in order to later iterate through in a ForEach loop, using Get-NetFirewallRules, and the AppIso rules are not accessible to this CmdLet, the script’s approach will fail to delete those rules. We’re simply using a Remove-ItemProperty command to purge it now. Rules1 and (original, Server2016) Rules2 will get cleared with the script w/o problems.
BR
Michael
Michael,
Do you happen to have an updated script with the new commands for the rules 2 section implemented? I am now discovering that the addition of DeleteUserAppContainersOnLogoff RegKey is causing some major issues during loggoff as you mentioned in your comment. Is it best to just remove the entire reg key and re-add?
Or are you basically doing the same with the reg keys with a separate script?
In a Server 2019, backup HKLM:\System\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\RestrictedServices\Configurable\System
Them delete and recreate this path:
Remove-Item “HKLM:\SYSTEM\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\RestrictedServices\Configurable\System”
New-Item “HKLM:\SYSTEM\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\RestrictedServices\Configurable\System”
After that, export HKLM:\SYSTEM\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\RestrictedServices\AppIso\FirewallRules and import into HKLM:\SYSTEM\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\RestrictedServices\Configurable\System
Execute the script with Windows Server 2016 path;
When completed, export HKLM:\SYSTEM\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\RestrictedServices\Configurable\System and import into HKLM:\SYSTEM\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\RestrictedServices\AppIso
Conclude restoring de backup of HKLM:\System\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\RestrictedServices\Configurable\System previously created.
Hello Michael
We have the same issue on all RDS server 2019. Yo say :
We’re simply using a Remove-ItemProperty command to purge it now. Rules1 and (original, Server2016) Rules2 will get cleared with the script w/o problems.
For Rules1 not problem but for Rules2 the script don’t works. I have no entry delete. How to delete all entry ?
This is the only thing that really works for me. Running it every night atm. Remove all firewall mess by deleting the registry key, recreate it and re-register appX packages.
Remove-Item “HKLM:\SYSTEM\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\RestrictedServices\Configurable\System”
New-Item “HKLM:\SYSTEM\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\RestrictedServices\Configurable\System”
Get-AppXPackage -AllUsers | Foreach {Add-AppxPackage -DisableDevelopmentMode -Register “$($_.InstallLocation)\AppXManifest.xml”}
Hope this helps someone.
Hi Jesper, tha KS for your feedback. It is important you add the registry entry suggested by Microsoft and restart the server for it to take effect. This will avoid encountering the issue again. I have applied this a number of times and it seems to have resolved it.