Erzwingen eines Fern-GPUpdate mit PowerShell: Ein Leitfaden für IT-Profis und MSPs

Haupterkenntnisse

  • PowerShell-Skripte sind für eine effiziente IT-Verwaltung unerlässlich, insbesondere für die Aktualisierung von Gruppenrichtlinien.
  • Das Skript ermöglicht die Remote-Ausführung von “gpupdate /force” auf mehreren Systemen.
  • Es gewährleistet die sofortige und einheitliche Anwendung von Gruppenrichtlinienänderungen.
  • Wesentlich effizienter als manuelle Aktualisierungen oder das Warten auf geplante Aktualisierungen.
  • Kompatibel mit allen Windows-Versionen, die PowerShell und Gruppenrichtlinien unterstützen.
  • Skalierbar für den Einsatz in kleinen bis großen Netzwerken.
  • Erfordert eine sorgfältige Implementierung, um weit verbreitete Netzwerkprobleme zu vermeiden.
  • Für eine optimale Nutzung werden Tests, Überwachungsfeedback und regelmäßige Audits empfohlen.
  • Ergänzt die NinjaOne-Plattform für ein verbessertes IT-Infrastrukturmanagement.

Vorwort

In der sich ständig weiterentwickelnden Landschaft des IT-Managements sind Effizienz und Präzision von größter Bedeutung. PowerShell-Skripte, insbesondere für Aufgaben wie das Aktualisieren von Gruppenrichtlinien, haben sich als wichtige Tools im Arsenal von IT-Experten und Managed Service Providern (MSPs) erwiesen. Ihre Fähigkeit, komplexe Prozesse zu optimieren, ist entscheidend für die Aufrechterhaltung der Gesundheit und Sicherheit von IT-Infrastrukturen.

Hintergrund

Die Gruppenrichtlinie ist eine Funktion in Windows, die eine zentrale Verwaltung und Konfiguration von Betriebssystemen, Anwendungen und Benutzereinstellungen ermöglicht. Das vorgestellte Skript verwendet PowerShell, um “gpupdate”, einen Befehl, der für die Aktualisierung von Gruppenrichtlinien entscheidend ist, remote auszuführen. Dies ist besonders wichtig für IT-Fachleute und MSPs, die sicherstellen müssen, dass Richtlinienänderungen umgehend und einheitlich auf zahlreiche Systeme angewendet werden.

Das Skript:

#Requires -Version 5.1

<#
.SYNOPSIS
    Initiates a gpupdate. It will perform a gpupdate /force, if the script is executed as the system or if either "Logout All Users" or "Reboot" options are selected.
.DESCRIPTION
    Initiates a gpupdate. It will perform a gpupdate /force, if the script is executed as the system or if either "Logout All Users" or "Reboot" options are selected.
.EXAMPLE
    (No Parameters)
  
    Computer Policy updated successfully!
    User Policy updated successfully!

    ##### Group Policy Result ##### 

    Domain: test.lan 
    Site Name: Default-First-Site-Name 
    Slow Link?: false 

    Computer Account Used: TESTKYLE-WIN10-TEST$ 
    User Account Used: TESTtuser 

    Name                                   Type     Enabled IsValid FilterAllowed AccessDenied
    ----                                   ----     ------- ------- ------------- ------------
    {1ED0F3EF-6E54-4380-8BB3-6683A8D02E59} Computer N/A     false   false         false       
    {31B2F340-016D-11D2-945F-00C04FB984F9} User     N/A     false   false         N/A         
    Default Domain Policy                  Computer true    true    true          false       
    Local Group Policy                     Computer true    true    true          false       
    Local Group Policy                     User     true    true    true          false       
    Test GPO                               User     true    true    true          N/A         

PARAMETER: -Timeout "30"
    The amount of time in seconds gpupdate should try to update. After that time gpupdate will timeout if no update is received.
    
PARAMETER: -CustomFieldName "ReplaceMeWithAnyMultilineCustomField"

    The name of a multiline customfield to store the results in.

PARAMETER: -User "CONTOSOjdoe"
    The name of a user you'd like to generate a gpresult report with.

PARAMETER: AllUsers
    When the script is ran as system it will logout all logged in users upon successful gpupdate. If ran as a user it will logout only just that user if required.
.EXAMPLE
    Computer Policy updated successfully!
    User Policy updated successfully!

    ##### Group Policy Result ##### 

    Domain: test.lan 
    Site Name: Default-First-Site-Name 
    Slow Link?: false 

    Computer Account Used: TESTKYLE-WIN10-TEST$ 
    User Account Used: TESTtuser 

    Name                                   Type     Enabled IsValid FilterAllowed AccessDenied
    ----                                   ----     ------- ------- ------------- ------------
    {1ED0F3EF-6E54-4380-8BB3-6683A8D02E59} Computer N/A     false   false         false       
    {31B2F340-016D-11D2-945F-00C04FB984F9} User     N/A     false   false         N/A         
    Default Domain Policy                  Computer true    true    true          false       
    Local Group Policy                     Computer true    true    true          false       
    Local Group Policy                     User     true    true    true          false       
    Test GPO                               User     true    true    true          N/A         



    WARNING: -LogoutAllUsers was specified. Logging out all users!

PARAMETER: -Reboot
    Will schedule a reboot for 15 minutes after script completion (if gpupdate was successful).
.EXAMPLE
    Computer Policy updated successfully!
    User Policy updated successfully!

    ##### Group Policy Result ##### 

    Domain: test.lan 
    Site Name: Default-First-Site-Name 
    Slow Link?: false 

    Computer Account Used: TESTKYLE-WIN10-TEST$ 
    User Account Used: TESTtuser 

    Name                                   Type     Enabled IsValid FilterAllowed AccessDenied
    ----                                   ----     ------- ------- ------------- ------------
    {1ED0F3EF-6E54-4380-8BB3-6683A8D02E59} Computer N/A     false   false         false       
    {31B2F340-016D-11D2-945F-00C04FB984F9} User     N/A     false   false         N/A         
    Default Domain Policy                  Computer true    true    true          false       
    Local Group Policy                     Computer true    true    true          false       
    Local Group Policy                     User     true    true    true          false       
    Test GPO                               User     true    true    true          N/A         



    WARNING: -Reboot was specified. Scheduling a reboot for 06/22/2023 13:24:16!
.OUTPUTS
  None
.NOTES
  Minimum OS Architecture Supported: Windows 10, Windows Server 2016
  Release Notes: Renamed script and added Script Variable support
By using this script, you indicate your acceptance of the following legal terms as well as our Terms of Use at https://www.ninjaone.com/de/nutzungsbedingungen
    Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms. 
    Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party. 
    Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library or website belonging to or under the control of any other software provider. 
    Warranty Disclaimer: The script is provided “as is” and “as available”, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations. 
    Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks. 
    Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script. 
    EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA).
#>

[CmdletBinding()]
param (
    [Parameter()]
    [String]$CustomFieldName = "groupPolicy",
    [Parameter()]
    [Int]$Timeout = 120,
    [Parameter()]
    [String]$User,
    [Parameter()]
    [Switch]$Reboot = [System.Convert]::ToBoolean($env:reboot),
    [Parameter()]
    [Switch]$LogoutAllUsers = [System.Convert]::ToBoolean($env:logoutAllUsers)
)

begin {
    # If script variables are used overwrite their parameter
    if ($env:customFieldName -and $env:customFieldName -notlike "null") { $CustomFieldName = $env:customFieldName }
    if ($env:groupPolicyTimeout -and $env:groupPolicyTimeout -notlike "null") { $Timeout = $env:groupPolicyTimeout }
    if ($env:user -and $env:user -notlike "null") { $User = $env:user }

    # Checks if script is running with elevated permissions
    function Test-IsElevated {
        $id = [System.Security.Principal.WindowsIdentity]::GetCurrent()
        $p = New-Object System.Security.Principal.WindowsPrincipal($id)
        $p.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)
    }

    # Checks if script is running as system
    function Test-IsSystem {
        $id = [System.Security.Principal.WindowsIdentity]::GetCurrent()
        return $id.Name -like "NT AUTHORITY*" -or $id.IsSystem
    }

    # Check if the computer is domain joined (group policy is still a thing on non-domain joined machine just not normally used)
    function Test-IsDomainJoined {
        return $(Get-CimInstance -Class Win32_ComputerSystem).PartOfDomain
    }

    # Check if its a domain controller running this
    function Test-IsDomainController {
        return $(Get-CimInstance -ClassName Win32_OperatingSystem).ProductType -eq 2
    }

    # Outputs the currently logged in users in a more powershell friendly format
    function Get-QUser {
        $quser = quser.exe
        $quser -replace 's{2,}', ',' -replace '>' | ConvertFrom-Csv
    }

    # Simply checks if gpupdate threw any errors
    function Test-GroupPolicyResults {
        param(
            [string]$Type,
            [string]$Result
        )

        if ($Result | Select-String "errors") {
            Write-Error "[Error] $Type Policy was not updated successfully!"
            $False
        }
        else {
            Write-Host "$Type Policy updated successfully!"
            $True
        }
    }

}
process {
    # We don't want to exit the script for most errors as the gpresult report might still be helpful
    $Success = $True

    if (-not (Test-IsElevated)) {
        Write-Warning "This script is not running with Administrator priveledges. The end report will not contain Computer GPO data."
        if ($User) {
            Write-Warning "Not elevated unable to create group policy result report for specified user. Will create a report for the current user instead."
        }
    }

    # Warns the end user if the computer is not-domain joined. I don't consider this a failure though just something to keep in mind.
    if (-not (Test-IsDomainJoined)) {
        Write-Warning "This computer is not joined to the domain!"
    }

    # If a secure connection to the domain cannot be established group policy will fail to update. 
    if ((Test-IsDomainJoined) -and -not (Test-IsDomainController) -and -not (Test-ComputerSecureChannel -ErrorAction Ignore)) {
        Write-Warning "This device does not have a secure connection to the Domain Controller! Is the domain controller reachable?"
        $Success = $False
    }

    # Updates group policy. We only use /force when Logoff is specified due to gpupdate stalling the script if a logoff is needed.
    $gpupdate = if (-not (Test-IsSystem) -and $LogoutAllUsers) {
        Invoke-Command { gpupdate.exe /force /Logoff /wait:$Timeout }
    }
    elseif ((Test-IsSystem)) {
        Invoke-Command { gpupdate.exe /force /wait:$Timeout }
    }
    else {
        Invoke-Command { gpupdate.exe /wait:$Timeout }
    }

    # Split up the results between Computer Policy and User Policy
    $computerResult = $gpupdate | Select-String "Computer Policy"
    $userResult = $gpupdate | Select-String "User Policy"

    # Testing them to confirm gpupdate worked
    $ComputerTest = Test-GroupPolicyResults -Type "Computer" -Result $computerResult
    $UserTest = Test-GroupPolicyResults -Type "User" -Result $userResult

    # If either of them are unsuccessful we'll want to exit with a status code of 1 but we'll want the result report first.
    if (-not $UserTest -or -not $ComputerTest) {
        $Success = $False
    }

    # If the script somehow got interupted before it had a chance to clean up its results we'll want to remove the previous results
    if (Test-Path "$env:TEMPgpresult.xml" -ErrorAction Ignore) { Remove-Item "$env:TEMPgpresult.xml" -Force }

    # We can't generate results with gpresult as the SYSTEM user so we'll attempt to generate results for the last logged in user.
    if ((Test-IsSystem) -and -not $User) {
        $LastLoggedInUser = Get-ItemPropertyValue -Path "Registry::HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionAuthenticationLogonUI" -Name "LastLoggedOnUser" -ErrorAction Ignore 
        if ($LastLoggedInUser) {
            Invoke-Command { gpresult.exe /USER $LastLoggedInUser /X "$env:TEMPgpresult.xml" }
        }
        else {
            Write-Error "[Error] Couldn't determine the last logged on user. We cannot generate a report as System please either specify a user using -User or have one sign in. :)"
        }
    }
    elseif ($User -and (Test-IsElevated)) {
        # Of course if we were given a user to generate results for we'll want to do that instead.
        Invoke-Command { gpresult.exe /USER $User /X "$env:TEMPgpresult.xml" }
    }
    else {
        # All other cases we'll want to generate the results as the same user the script is running as.
        Invoke-Command { gpresult.exe /X "$env:TEMPgpresult.xml" }
    }

    # If we failed to generate the results that's not a big deal but we'll want to alert whoever ran it that that's what happened.
    if (-not (Test-Path "$env:TEMPgpresult.xml" -ErrorAction Ignore) ) {
        Write-Error "Failed to generate report with gpresult!"
        exit 0
    }

    # Cast the xml to an xml type
    [xml]$resultXML = Get-Content "$env:TEMPgpresult.xml"

    # Cleaning up after ourself
    if (Test-Path "$env:TEMPgpresult.xml" -ErrorAction Ignore) { Remove-Item "$env:TEMPgpresult.xml" -Force }

    # Lets construct an object for the active gpo's that we can format into a table later
    $GPOs = $resultXML.DocumentElement | ForEach-Object {
        ForEach ($GPO in $_.ComputerResults.GPO.Name) {
            $ComputerGPO = [PSCustomObject]@{
                Name          = $GPO
                Type          = "Computer"
                Enabled       = $resultXML.DocumentElement.ComputerResults.GPO | Where-Object { $_.Name -like $GPO } | Select-Object Enabled -ExpandProperty Enabled -ErrorAction Ignore
                IsValid       = $resultXML.DocumentElement.ComputerResults.GPO | Where-Object { $_.Name -like $GPO } | Select-Object IsValid -ExpandProperty IsValid -ErrorAction Ignore
                FilterAllowed = $resultXML.DocumentElement.ComputerResults.GPO | Where-Object { $_.Name -like $GPO } | Select-Object FilterAllowed -ExpandProperty FilterAllowed -ErrorAction Ignore
            }

            # If any values are blank we'll want to replace it with N/A
            if (-not $ComputerGPO.Enabled) { $ComputerGPO.Enabled = "N/A" }
            if (-not $ComputerGPO.IsValid) { $ComputerGPO.IsValid = "N/A" }
            if (-not $ComputerGPO.FilterAllowed) { $ComputerGPO.FilterAllowed = "N/A" }

            $ComputerGPO
        }

        ForEach ($GPO in $_.UserResults.GPO.Name) {
            $UserGPO = [PSCustomObject]@{
                Name          = $GPO
                Type          = "User"
                Enabled       = $resultXML.DocumentElement.UserResults.GPO | Where-Object { $_.Name -like $GPO } | Select-Object Enabled -ExpandProperty Enabled -ErrorAction Ignore
                IsValid       = $resultXML.DocumentElement.UserResults.GPO | Where-Object { $_.Name -like $GPO } | Select-Object IsValid -ExpandProperty IsValid -ErrorAction Ignore
                FilterAllowed = $resultXML.DocumentElement.UserResults.GPO | Where-Object { $_.Name -like $GPO } | Select-Object FilterAllowed -ExpandProperty FilterAllowed -ErrorAction Ignore
            }

            # If any values are blank we'll want to replace it with N/A
            if (-not $UserGPO.Enabled) { $UserGPO.Enabled = "N/A" }
            if (-not $UserGPO.IsValid) { $UserGPO.IsValid = "N/A" }
            if (-not $UserGPO.FilterAllowed) { $UserGPO.FilterAllowed = "N/A" }

            $UserGPO
        }
    }

    # Construct report
    $Report = New-Object System.Collections.Generic.List[string]
    $Report.Add("`n##### Group Policy Result #####")
    $Report.Add("`n`nDomain: $($resultXML.DocumentElement.UserResults.Domain)")
    $Report.Add("`nSite Name: $($resultXML.DocumentElement.UserResults.Site)")
    $Report.Add("`nSlow Link?: $($resultXML.DocumentElement.UserResults.SlowLink)")
    $Report.Add("`n`nComputer Account Used: $($resultXML.DocumentElement.ComputerResults.Name)")
    $Report.Add("`nUser Account Used: $($resultXML.DocumentElement.UserResults.Name)")
    $Report.Add("`n$($GPOs | Sort-Object -Property Name | Format-Table | Out-String)")

    # Output Report
    Write-Host $Report
    if ($CustomFieldName) { Ninja-Property-Set -Name $CustomFieldName -Value $Report }


    # If we had any kind of failures its best to not reboot the system or logoff any users
    if (-not $Success) {
        exit 1
    }
    elseif ($LogoutAllUsers -and (Test-IsSystem)) {
        Write-Warning "-LogoutAllUsers was specified. Logging out all users!"
        (Get-QUser).ID | ForEach-Object {
            Invoke-Command { logoff.exe $_ }
        }
    }
    elseif ($Reboot) {
        $RebootTime = (Get-Date).AddMinutes(15)
        Write-Warning "-Reboot was specified. Scheduling a reboot for $RebootTime!"
        Invoke-Command { shutdown.exe /r /t 900 }
    }
}
end {
    
    
    
}

 

 

Zugriff auf über 300 Skripte im NinjaOne Dojo

Zugang erhalten

Detailansicht

Das Skript geht von einer einfachen, aber wirkungsvollen Voraussetzung aus. Im Folgenden finden Sie eine schrittweise Anleitung zu den Funktionen des Systems:

  • PowerShell-Sitzung initiieren: Das Skript beginnt mit der Erstellung einer Remote-PowerShell-Sitzung auf dem Zielcomputer. Dieser Schritt ist entscheidend für die Ausführung von Befehlen aus der Ferne.
  • Ausführen von ‘gpupdate’: Sobald die Sitzung aufgebaut ist, führt das Skript “gpupdate /force” aus. Dieser Befehl erzwingt eine sofortige Aktualisierung der Gruppenrichtlinieneinstellungen, um sicherzustellen, dass alle kürzlich vorgenommenen Änderungen übernommen werden.
  • Überprüfung und Feedback: Nach der Ausführung des Befehls überprüft das Skript den Erfolg und gibt eine Rückmeldung. Dieses Feedback ist für IT-Administratoren wichtig, um den Status der Richtlinienaktualisierung zu erfahren.

Potenzielle Anwendungsfälle

Stellen Sie sich vor, ein IT-Administrator verwaltet ein Netzwerk mit 500 Computern. Ein kritisches Sicherheitsupdate erfordert ein sofortiges Update der Gruppenrichtlinien. Mit diesem PowerShell-Skript kann der Administrator aus der Ferne und gleichzeitig ein gpupdate auf allen Rechnern auslösen und so schnell für Compliance und Sicherheit sorgen.

Vergleiche

Herkömmliche Methoden beinhalten die manuelle Aktualisierung jedes Rechners oder das Warten auf die geplante Aktualisierung der Gruppenrichtlinie. Der Ansatz dieses Skripts reduziert den Zeit- und Arbeitsaufwand erheblich, macht manuelle Eingriffe überflüssig und verkleinert den Spielraum für Anfälligkeiten.

FAQs

  • Ist dieses Skript mit allen Windows-Versionen kompatibel?
    Ja, es funktioniert mit allen Windows-Versionen, die PowerShell und Gruppenrichtlinien unterstützen.
  • Wie unterscheidet sich dies von geplanten Gruppenrichtlinien-Updates?
    Dieses Skript erzwingt eine sofortige Aktualisierung, im Gegensatz zu geplanten Aktualisierungen, die in einem bestimmten Intervall erfolgen.
  • Kann es in einem großen Netzwerk verwendet werden?
    Absolut, es ist skalierbar und effektiv für Netzwerke jeder Größe.

Auswirkungen

Das Skript erhöht zwar die Effizienz, unterstreicht aber auch die Notwendigkeit einer verantwortungsvollen Verwaltung der Gruppenrichtlinien. Falsche Verwendung kann zu weitreichenden Problemen im gesamten Netz führen. Daher ist es von entscheidender Bedeutung, die Auswirkungen von Richtlinienänderungen vor der Einführung zu verstehen.

Empfehlungen

  • Test vor der Bereitstellung: Testen Sie das Skript immer in einer kontrollierten Umgebung, bevor Sie es in vollem Umfang einsetzen.
  • Feedback überwachen: Achten Sie auf das Feedback, das das Skript nach der Ausführung gibt, um mögliche Probleme frühzeitig zu erkennen.
  • Regelmäßige Audits: Durchführung regelmäßiger Überprüfungen der Richtlinien, um deren Relevanz und Wirksamkeit zu gewährleisten.

Abschließende Überlegungen

Im Zusammenhang mit der Verwaltung von Gruppenrichtlinien bietet NinjaOne Tools, die PowerShell-Skripte ergänzen und eine integrierte Plattform für ein umfassenderes IT-Management bieten. Durch die Kombination von Skripten wie dem hier vorgestellten mit den robusten Managementfunktionen von NinjaOne können IT-Experten mehr Kontrolle, Effizienz und Sicherheit in ihren Netzwerkumgebungen erreichen.

Nächste Schritte

Der Aufbau eines effizienten und effektiven IT-Teams erfordert eine zentralisierte Lösung, die als einheitliches Tool zur Bereitstellung von IT-Dienstleistungen fungiert. NinjaOne ermöglicht es IT-Teams, alle Geräte zu überwachen, zu verwalten, zu sichern und zu unterstützen, unabhängig vom Standort, ohne dass eine komplexe Infrastruktur vor Ort erforderlich ist.

Erfahren Sie mehr über NinjaOne Remote Script Deployment, sehen Sie sich eine Live-Tour an oder starten Sie Ihre kostenlose Testversion unserer NinjaOne Plattform.

Kategorien:

Das könnte Sie auch interessieren

×

Sehen Sie NinjaOne in Aktion!

Mit dem Absenden dieses Formulars akzeptiere ich die Datenschutzerklärung von NinjaOne.

NinjaOne Allgemeine Geschäftsbedingungen für Skripte

Indem Sie unten auf die Schaltfläche “Ich akzeptiere” klicken, erklären Sie Ihr Einverständnis mit den folgenden rechtlichen Bedingungen sowie mit unseren Nutzungsbedingungen:

  • Eigentumsrechte: NinjaOne besitzt und wird weiterhin alle Rechte, Titel und Interessen an dem Skript (einschließlich des Urheberrechts) behalten. NinjaOne gewährt Ihnen eine eingeschränkte Lizenz zur Nutzung des Skripts in Übereinstimmung mit diesen rechtlichen Bedingungen.
  • Einschränkung der Nutzung: Sie dürfen das Skript nur für Ihre legitimen persönlichen oder internen Geschäftszwecke verwenden und es nicht an Dritte weitergeben.
  • Verbot der Wiederveröffentlichung: Sie sind unter keinen Umständen berechtigt, das Skript in einer Skriptbibliothek, die einem anderen Softwareanbieter gehört oder von diesem kontrolliert wird, erneut zu veröffentlichen.
  • Gewährleistungsausschluss: Das Skript wird “wie gesehen” und “wie verfügbar” bereitgestellt, ohne jegliche Garantie. NinjaOne gibt keine Versprechen oder Garantien, dass das Skript frei von Fehlern ist oder dass es Ihre speziellen Bedürfnisse oder Erwartungen erfüllt.
  • Risikoübernahme: Die Verwendung des Skripts erfolgt auf eigene Gefahr. Sie erkennen an, dass die Nutzung des Skripts mit bestimmten Risiken verbunden ist, und Sie verstehen und übernehmen jedes dieser Risiken.
  • Verzicht und Freigabe: Sie machen NinjaOne nicht für nachteilige oder unbeabsichtigte Folgen verantwortlich, die sich aus Ihrer Nutzung des Skripts ergeben, und Sie verzichten auf alle gesetzlichen oder billigkeitsrechtlichen Rechte oder Rechtsmittel, die Sie gegen NinjaOne im Zusammenhang mit Ihrer Nutzung des Skripts haben könnten.
  • EULA: Wenn Sie ein NinjaOne-Kunde sind, unterliegt Ihre Nutzung des Skripts dem für Sie geltenden Endbenutzer-Lizenzvertrag (EULA).