Windows Server 2016 RDS Effekte (Black Screen, Startmenü defekt)

Problem:

Ein Terminal Server (RDS Session Host) zeigt nach einiger Zeit verschiedene Effekte, wie z.B. „schwarzer Bildschirm nach der Anmeldung“, „nicht mehr funktionierendes Startmenü“, allgemeine Performance- oder Anmeldeprobleme.

Dies betrifft übrigens nicht zwingend nur RDS Sitzungshosts, sondern prinzipiell alle Windows Server 2016 Maschinen, auf Terminalservern (insbesondere mit User Profile Disks, UPDs) ist das ganze aufgrund potenziell größerer Anmelde-/Benutzeranzahl nur deutlich wahrscheinlicher anzutreffen.

Lösung:

Schuld könnte ein Bug sein, welcher dafür sorgt, dass bei der Benutzeranmeldung erstellte Firewall-Regeln beim löschen des Benutzerprofils (hier kommen die UPDs ins Spiel, unter Einsatz dieser wird das Profil nämlich bei der Abmeldung automatisch wieder vom Server gelöscht) nicht mehr entfernt werden.

Das verursacht einen Registry-Bloat in 

HKLM:\System\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\FirewallRules

und/oder

HKLM:\System\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\RestrictedServices\Configurable\System

Sind diese Keys bereits „überfüllt“, kann es gut sein, dass sich die Werte nicht mehr per GUI (regedit) entfernen lassen – der Key lädt schlichtweg Ewigkeiten und stürzt bei zu wenig RAM ab.

Abhilfe schafft unser kleines PowerShell-Script, das die Einträge nacheinander löscht:

$profiles = get-wmiobject -class win32_userprofile
Clear-Host
Write-Host "`n`n`n`n`n`n`n`n"
Write-Host "Getting Firewall Rules..."
$Rules1 = Get-NetFirewallRule -All | 
  Where-Object {$profiles.sid -notcontains $_.owner -and $_.owner }
$Rules1Count = $Rules1.count
Write-Host "" $Rules1Count "Rules`n"

Write-Host "Getting Firewall Rules from ConfigurableServiceStore..."
$Rules2 = Get-NetFirewallRule -All -PolicyStore ConfigurableServiceStore | 
  Where-Object { $profiles.sid -notcontains $_.owner -and $_.owner }
$Rules2Count = $Rules2.count
Write-Host "" $Rules2Count "Rules`n"

$Total = $Rules1.count + $Rules2.count
Write-Host "Deleting" $Total "Firewall Rules:" -ForegroundColor Green

$Result = Measure-Command {

  $start = (Get-Date)
  $i = 0.0

  foreach($rule1 in $Rules1){

    # action
    Remove-ItemProperty -Path "HKLM:\System\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\FirewallRules" -Name $rule1.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
  }

  foreach($rule2 in $Rules2) {

    # action  
    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
    $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 from ConfugurableServiceStore 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

Achtung: bei einem bereits länger laufenden Terminalserver, kann das Script schonmal so ein paar Stunden brauchen um alle Regeln zu entfernen. In einem Fall hier knapp 4 Stunden für etwa 95000 Regeln. Je nach CPU kann das natürlich etwas schneller gehen oder länger dauern – es wird wirklich fertig.

Aus jenen Performancegründen löscht das Script die Registry-Werte direkt, anstatt das eigentlich korrekte Remove-NetFirewallRule Cmdlet zu verwenden.

18 Replies to “Windows Server 2016 RDS Effekte (Black Screen, Startmenü defekt)”

  1. Hallo
    Grundsätzlich ein sehr hilfreiches Script, welches ich bereits diverse Male erfolgreich eingesetzt habe.
    Dennoch habe ich diverse Server, die anscheinend zu lange laufen und das Script schlägt fehl.
    Der Server hat 32GB RAM und dennoch diese Meldung:

    Getting Firewall Rules…
    0 Rules

    Getting Firewall Rules from ConfigurableServiceStore…
    Get-NetFirewallRule : Für diesen Vorgang ist nicht genügend Speicher verfügbar.
    In C:\Clear-RdsFirewallRules.ps1:11 Zeichen:11
    + $Rules2 = Get-NetFirewallRule -All -PolicyStore ConfigurableServiceSt …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (MSFT_NetFirewallRule:root/standardcimv2/MSFT_NetFirewallRule) [Get-NetFir
    ewallRule], CimException
    + FullyQualifiedErrorId : Windows System Error 14,Get-NetFirewallRule

    0 Rules

    Deleting 0 Firewall Rules:
    end 09.03.2020 21:09:05
    eta
    0 min 0 sec

    • Das geschieht dann, wenn die Liste der Objekte zu groß wird. Hier hilft meistens der Parameter -AsJob oder einfach Stückweise durch die Liste iterieren.

      • Hallo!

        Danke für deine Hilfe!

        Jedoch komme ich noch immer nicht ins Startmenü!

        Wir verwenden einen Windows Server 2019 als Terminalserver in einer Sammlung.
        Beim lokalen Admin funktioniert das Startmenü und sobald ich mich als Domain Admin oder als User anmelde geht es nicht mehr.

        Ich hab schon einen anderen Server aus der Sammlung geclont – danach Sysprep – neu eingebunden ….
        … gleiches Problem.
        Hat von euch da noch jemand eine Ahnung?
        glg
        Andi

        • Was sagt dein Ereignisprotokoll (Anwendungen)? In der Regel stehen da mehr Details drin. Verwendest du beispielsweise nicht die Default-Profilpfade, stürzt der Searchhost (ohne den geht das Startmenü irritierenderweise nicht) ab.

          • AppLocker kann auch schuld sein. Ist Cortana nicht erlaubt, geht auch das Startmenü nicht. Regel auf Cortana (oder alle signierten) zulassen geändert, gpupdate, dann gings sofort wieder.

        • Hallo, wir haben auch drei WTS mit win2019 im Einsatz. Leider haben wir auch die Startmenü Probleme das es nicht mehr angezeigt wird. Wir arbeiten mit Benutzerprofil-Datenträger. Was auch gut klappt. Skript usw. was oben steht habe ich alles schon gemacht. Gibt es ggf neue Lösungen?

      • Hallo,

        ich habe leider auch einen Server bei dem es zu viele Ergebnisse für den ConfigurableServiceStore gibt. Und mir ist leider auch nicht klar wie ich hier mit dem „AsJob“ weiterkommen soll. Ist die Idee das ganze Script so zu starten? Hatte schon mal das Get-NetFirewallRule mit „AsJob“ laufen lassen, aber das hilft natürlich nichts weil dann das ohne Ergebniss einfach weiter läuft. Hätte jemand einen Tip für mich?

  2. Vielleicht ein blöder Zufall aber seit ich das obige Script ausgeführt habe funktioniert Office 2016 pro plus nicht mehr. Hatte dieses Phänomen nun gerade bei zwei Kunden bei welchen ich testweise das Script ausgeführt habe. (Winword starten –> Programm funktioniert nicht mehr). Eine Neuinstallation von Office scheint nun geholfen zu haben.

    • Hast du auf den Servern vielleicht die Firewall eingeschaltet und verwendest keine benutzerdefinierten Regeln (via GPO oder ähnliches)? Das Script löscht alle Regeln, die beim Anmelden erzeugt werden. Das gilt auch für die Office-Updater und Lizenzierungs-Ausnahmen … die müsstest du schon anders hinzufügen. Oder die Firewall abschalten.

      Mit allem anderen hat dieses Script nichts zu tun.

  3. AppLocker ist bei uns nicht eingeschalten.

    Ich hab jetzt bei 8 Terminalservern jetzt diesen RegKey gesetzt und die 2 Ordnerinhalte gelöscht.

    Jetzt fängt das mit dem Startmenü wieder an ….
    Hat noch jemand eine Ahnung ?

    Was mir noch aufgefallen ist, die User bekommen nach dem Anmelden einen ca. 1 minütigen Blackscreen und bei der Abmeldung kommt die Meldung Warten auf Benutzerprofildienst ….

    • Leider kann der Startmenüeffekt viele verschiedene Ursachen haben. Diese können sich in jeder Umgebung anders äußern.

      Probleme machen häufig Profilbezogene Dinge: Roaming-Profiles, Ordnerumleitungen, UserProfileDisks (UDPs), …
      Microsoft empfiehlt mittlerweile das alles durch FSLogix „Profile Container“ abzulösen (https://docs.microsoft.com/en-us/fslogix/)
      Getestet haben wir das bisher nicht.
      In einer der größeren RDS-SH-Collection hatten wir in Verbindung mit UPDs und dem beschriebenen Script weitestgehend keine Probleme mehr, sofern ein Benutzer sich nicht zufällig schnell von seiner Collection ab- und anmeldet und das mounten der UPD dadurch fehlschlägt.

      Ich bin allerdings nicht ganz sicher, welche RegistryKeys du hier gesetzt und welche Ordner du gelöscht hast. Das Script löscht Werte innerhalb der beiden genannten RegistryKeys. (Genaugenommen sind das Benutzerbezogene Firewallregeln.)

  4. Hallo,

    erstmal danke für die Mühe

    eine Frage habe ich aber , ich habe das Skript so verstanden das es die Einträge in der Registry löscht , oder liege ich das Falsch.
    Den die ganze Einträge sind noch vorhanden.

  5. Hallo,
    wir haben auch das Problem beim zweiten Teil der Regeln „$Rules2 = Get-NetFirewallRule -All -PolicyStore ConfigurableServiceStore | Where-Object { $profiles.sid -notcontains $_.owner -and $_.owner }“,

    => Get-NetFirewallRule : Für diesen Vorgang ist nicht genügend Speicher verfügbar.

    Bei der ersten Lösung sind es 67T Einträge. -AsJob hat nicht funktioniert bzw. wie wird es genutzt?

    • Hallo zusammen,

      ich hatte auch das Problem mit „Get-NetFirewallRule : Für diesen Vorgang ist nicht genügend Speicher verfügbar.“
      Das liegt daran, dass zu viele Firewall Regel Objekte unter dem Schlüssel
      „HKLM:\System\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\RestrictedServices\Configurable\System“ gespeichert sind (in meinem Fall waren es bei 3 RD-Servern jeweils über 130.000 Objekte) und Powershell wohl ein Limit der Variablengröße / Objektanzahl überschreitet.
      Den Trick mit „AsJob“ Parameter habe ich leider nicht verstanden und auch nicht umsetzen können.

      Fix: „HKLM:\System\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\RestrictedServices\Configurable“ umbenennen. Der Schlüssel „System“ darf nicht angeklickt werden, sonst hängt sich Regedit auf und man kommt nur per Kill raus!
      Unmittelbar danach wird vom System automatisch der umbenannte Schlüssel „Configurable“ wieder erstellt (mit F5 aktualisieren).
      Danach muss man noch den untergeordneten Schlüssel „System“ manuell anlegen und den Server neu starten.
      Danach funktioniert der Skript wieder einwandfrei, wenn man ihn regelmäßig ausführt.

      P.S.: der vorher umbenannte Schlüssel „Configurable_old“ lässt sich dann auch via Regedit exportieren (dauert!!!).

      Hoffentlich hilft das noch jemandem.

      VG
      Alex

  6. Hallo, wenn ich das richtig verstanden habe, benötige ich das tool nur wenn die Registry nicht manuell zu löschen geht.
    Bei mir (WIN SRV 2016 1 Broker 4 Sitzungshost) ging es manuell, es hat mir aber die ganzen FW Regeln für die Serverfarm zerschossen und ich hatte vom Verbindungsbroker keinen zugriff mehr(RDP zulassen/Sperren). Oder darf man hier nur Bestimmte Regeln löschen?

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.