Comment forcer GPUpdate à distance avec PowerShell : le guide pour les professionnels de l’informatique et les entreprises MSP

Principaux points à retenir

  • Les scripts PowerShell sont essentiels pour une gestion informatique efficace, en particulier pour les mises à jour de la stratégie de groupe (Group Policy ou GP).
  • Le script facilite l’exécution à distance de ‘gpupdate /force’ sur plusieurs systèmes.
  • Il garantit une application immédiate et uniforme des modifications apportées à la stratégie de groupe.
  • Beaucoup plus efficace que les mises à jour manuelles ou l’attente de celles planifiées.
  • Compatible avec toutes les versions de Windows prenant en charge PowerShell et la stratégie de groupe.
  • Évolutif, il peut être utilisé sur des réseaux de petite ou de grande taille.
  • Nécessite une implémentation avec prudence afin d’éviter des problèmes de réseau généralisés.
  • Pour une utilisation optimale, il est recommandé de procéder à des tests, de contrôler le retour d’information et d’effectuer des audits réguliers.
  • Complète la plateforme NinjaOne pour une meilleure gestion de l’infrastructure informatique.

Introduction

La gestion informatique étant en constante évolution, l’efficacité et la précision sont primordiales. Les scripts PowerShell, en particulier pour des tâches telles que la mise à jour de la stratégie de groupe, sont devenus des outils essentiels dans l’arsenal des professionnels de l’informatique et des fournisseurs de services gérés (MSP). Leur capacité à simplifier des processus complexes est essentielle pour maintenir la santé et la sécurité des infrastructures informatiques.

Contexte

La stratégie de groupe est une fonctionnalité de Windows qui permet de centraliser la gestion et la configuration des systèmes d’exploitation, des applications et des paramètres des utilisateurs. Le script que nous vous présentons utilise PowerShell pour exécuter à distance ‘gpupdate’, une commande essentielle pour actualiser les stratégies de groupe. Ceci est particulièrement important pour les professionnels de l’informatique et les MSP qui doivent s’assurer que les changements de stratégie sont appliqués rapidement et uniformément dans de nombreux systèmes.

Le script :

#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/terms-of-use.
    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 {
    
    
    
}

 

 

Accédez à plus de 700 scripts dans le Dojo NinjaOne

Obtenir l’accès

Description détaillée

Le script repose sur une base simple mais performante. Voici une description détaillée de son fonctionnement :

  • Ouverture d’une session PowerShell: Le script commence par créer une session PowerShell à distance sur la machine cible. Cette étape est cruciale pour l’exécution de commandes à distance.
  • Exécution de ‘gpupdate’: Une fois la session établie, le script exécute ‘gpupdate /force’. Cette commande permet d’actualiser immédiatement les paramètres de la stratégie de groupe, ce qui garantit l’application de toutes les modifications récentes.
  • Vérification et retour d’information: Après avoir exécuté la commande, le script vérifie sa réussite et fournit un retour d’information. Ce retour d’information est essentiel pour que les administrateurs informatiques sachent où en est la mise à jour de la stratégie.

Cas d’utilisation potentiels

Imaginez un administrateur informatique gérant un réseau de 500 ordinateurs. Une mise à jour de sécurité critique nécessite une mise à jour immédiate de la stratégie de groupe. Grâce à ce script PowerShell, l’administrateur peut déclencher à distance et simultanément une mise à jour (gpupdate) sur toutes les machines, garantissant ainsi rapidement la conformité et la sécurité.

Comparaisons

Les méthodes traditionnelles consistent à mettre à jour manuellement chaque machine ou à attendre l’actualisation programmée de la stratégie de groupe. L’approche de ce script réduit considérablement le temps et les efforts, en éliminant le besoin d’une intervention manuelle et en réduisant la période de vulnérabilité.

FAQ

  • Ce script est-il compatible avec toutes les versions de Windows ?
    Oui, il fonctionne avec toutes les versions de Windows qui prennent en charge PowerShell et la stratégie de groupe.
  • Quelle est la différence avec les mises à jour planifiées de la stratégie de groupe ?
    Ce script force une mise à jour immédiate, contrairement aux mises à jour programmées qui suivent un intervalle défini.
  • Peut-il être utilisé sur un grand réseau ?
    Absolument, il est évolutif et efficace pour les réseaux de toute taille.

Implications

Ce script améliore l’efficacité et souligne également la nécessité d’une gestion responsable de la stratégie de groupe. Une utilisation incorrecte peut entraîner des problèmes généralisés sur le réseau. Il est donc essentiel de comprendre l’impact des changements de stratégie avant de procéder au déploiement.

Recommandations

  • Tester avant de déployer: Testez toujours le script dans un environnement contrôlé avant de le déployer à grande échelle.
  • Vérifier le retour d’information: Soyez attentif au retour d’information fourni par le script après son exécution afin de détecter rapidement tout problème potentiel.
  • Audits réguliers: Réalisez des audits réguliers des stratégies afin d’en garantir la pertinence et l’efficacité.

Conclusion

Dans le cadre de la gestion des stratégies de groupe, NinjaOne propose des outils qui complètent les scripts PowerShell, offrant ainsi une plateforme intégrée pour une gestion informatique plus complète. En associant des scripts tels que celui présenté ici aux solides capacités de gestion de NinjaOne, les professionnels de l’informatique peuvent améliorer le contrôle, l’efficacité et la sécurité de leur réseau.

Pour aller plus loin

Pour créer une équipe informatique efficace et performante, il est essentiel d'avoir une solution centralisée qui joue le rôle de nœud principal pour vos services. NinjaOne permet aux équipes informatiques de surveiller, gérer, sécuriser et prendre en charge tous les appareils, où qu'ils soient, sans avoir besoin d'une infrastructure complexe sur site. Pour en savoir plus sur NinjaOne Endpoint Management, participez à une visite guidée, ou profitez d'un essai gratuit de la plateforme NinjaOne.

Catégories :

Vous pourriez aussi aimer

×

Voir NinjaOne en action !

En soumettant ce formulaire, j'accepte la politique de confidentialité de NinjaOne.

Termes et conditions NinjaOne

En cliquant sur le bouton “J’accepte” ci-dessous, vous indiquez que vous acceptez les termes juridiques suivants ainsi que nos conditions d’utilisation:

  • Droits de propriété: NinjaOne possède et continuera de posséder tous les droits, titres et intérêts relatifs au script (y compris les droits d’auteur). NinjaOne vous accorde une licence limitée pour l’utilisation du script conformément à ces conditions légales.
  • Limitation de l’utilisation: Les scripts ne peuvent être utilisés qu’à des fins personnelles ou professionnelles internes légitimes et ne peuvent être partagés avec d’autres entités.
  • Interdiction de publication: Vous n’êtes en aucun cas autorisé à publier le script dans une bibliothèque de scripts appartenant à, ou sous le contrôle d’un autre fournisseur de logiciels.
  • Clause de non-responsabilité: Le texte est fourni “tel quel” et “tel que disponible”, sans garantie d’aucune sorte. NinjaOne ne promet ni ne garantit que le script sera exempt de défauts ou qu’il répondra à vos besoins ou attentes particulières.
  • Acceptation des risques: L’utilisation du script est sous votre propre responsabilité. Vous reconnaissez qu’il existe certains risques inhérents à l’utilisation du script, et vous comprenez et assumez chacun de ces risques.
  • Renonciation et exonération de responsabilité: Vous ne tiendrez pas NinjaOne pour responsable des conséquences négatives ou involontaires résultant de votre utilisation du script, et vous renoncez à tout droit ou recours légal ou équitable que vous pourriez avoir contre NinjaOne en rapport avec votre utilisation du script.
  • EULA: Si vous êtes un client de NinjaOne, votre utilisation du script est soumise au contrat de licence d’utilisateur final qui vous est applicable (End User License Agreement (EULA)).