Guarda una demo×
×

Guarda NinjaOne in azione!

Inviando questo modulo, accetto La politica sulla privacy di NinjaOne.

Come forzare GPUpdate da remoto con PowerShell: una guida per professionisti IT e MSP

Punti chiave

  • Gli script PowerShell sono fondamentali per una gestione IT efficiente, soprattutto per gli aggiornamenti dei Criteri di gruppo.
  • Lo script facilita l’esecuzione remota del comando “gpupdate /force” su più sistemi.
  • Garantisce l’applicazione immediata e uniforme delle modifiche ai Criteri di gruppo.
  • Lo script per forzare GPUpdate da remoto è molto più efficiente degli aggiornamenti manuali o dell’attesa di aggiornamenti programmati.
  • Compatibile con tutte le versioni di Windows che supportano PowerShell e Criteri di gruppo.
  • Scalabile per l’utilizzo in reti di piccole e grandi dimensioni.
  • Richiede un’attenta implementazione per evitare problemi di rete diffusi.
  • Per un utilizzo ottimale, si raccomanda di eseguire test, monitorare i feedback e svolgere verifiche periodiche.
  • Integra la piattaforma NinjaOne per una migliore gestione dell’infrastruttura IT.

Introduzione

Nel panorama in continua evoluzione della gestione IT, efficienza e precisione sono fondamentali. Gli script PowerShell, in particolare per attività come l’aggiornamento dei Criteri di gruppo, sono emersi come strumenti vitali nell’arsenale dei professionisti IT e dei Managed Service Provider (MSP). La loro capacità di semplificare processi complessi è fondamentale per mantenere lo stato di salute e la sicurezza delle infrastrutture IT.

Background

I criteri di gruppo sono una funzione di Windows che consente la gestione e la configurazione centralizzata di sistemi operativi, applicazioni e impostazioni relative agli utenti. Lo script su cui ci concentriamo utilizza PowerShell per eseguire in remoto “gpupdate”, un comando fondamentale per aggiornare i Criteri di gruppo. Ciò è particolarmente importante per i professionisti IT e gli MSP che devono garantire che le modifiche ai criteri vengano applicate tempestivamente e in modo uniforme su numerosi sistemi.

Lo script per forzare GPUpdate da remoto:

#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/it/condizioni-utilizzo
    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 {
    
    
    
}

|

#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 {
    
    
    
}

 

 

Accedi a oltre 700 script nel Dojo di NinjaOne

Ottieni l’accesso

Analisi dettagliata

Lo script per lanciare GPUpdate da remoto si basa su una premessa semplice ma potente. Ecco una guida passo per passo delle sue funzionalità:

  • Avvio della sessione PowerShell: Lo script per forzare GPUpdate da remoto inizia creando una sessione PowerShell remota sul computer di destinazione. Questo passaggio è fondamentale per l’esecuzione di comandi in remoto.
  • Esecuzione di “gpupdate”: Una volta stabilita la sessione, lo script esegue “gpupdate /force”. Questo comando forza l’esecuzione di un aggiornamento immediato delle impostazioni dei Criteri di gruppo, garantendo l’applicazione di tutte le modifiche recenti.
  • Verifica e feedback: Dopo l’esecuzione del comando, lo script per forzare GPUpdate da remoto ne verifica il successo e fornisce un feedback. Questo feedback è essenziale per gli amministratori IT per conoscere lo stato dell’aggiornamento dei criteri.

Casi d’uso potenziali

Immagina un amministratore IT che gestisce una rete di 500 computer. Un aggiornamento di sicurezza critico richiede un aggiornamento immediato dei Criteri di gruppo. Utilizzando questo script PowerShell per forzare GPUpdate da remoto, l’amministratore può attivare da remoto, e simultaneamente, un gpupdate su tutti i computer, garantendo rapidamente la conformità e la sicurezza.

Confronti

I metodi tradizionali prevedono l’aggiornamento manuale di ogni computer o l’attesa dell’aggiornamento programmato dei Criteri di gruppo. L’approccio di questo script riduce il tempo e l’impegno richiesti in modo significativo, eliminando la necessità di interventi manuali e riducendo la finestra di vulnerabilità.

Domande frequenti

  • Questo script per forzare GPUpdate da remoto è compatibile con tutte le versioni di Windows?
    Sì, funziona con tutte le versioni di Windows che supportano PowerShell e i Criteri di gruppo.
  • Che differenza c’è tra questo script per forzare GPUpdate da remoto e gli aggiornamenti programmati dei Criteri di gruppo?
    Questo script per forzare GPUpdate da remoto forza un aggiornamento immediato, a differenza degli aggiornamenti programmati che seguono una programmazione prestabilita.
  • Può essere utilizzato su una rete di grandi dimensioni?
    Assolutamente sì, è scalabile ed efficace per reti di qualsiasi dimensione.

Implicazioni

Se da un lato lo script per forzare GPUpdate da remoto migliora l’efficienza, dall’altro è importante sottolineare la necessità di una gestione responsabile dei Criteri di gruppo. Un utilizzo non corretto può causare problemi diffusi in tutta la rete. Per questo motivo, è fondamentale comprendere l’impatto delle modifiche a un criterio prima dell’implementazione.

Raccomandazioni

  • Testa prima della distribuzione: Testa sempre lo script per forzare GPUpdate da remoto in un ambiente controllato prima della distribuzione su larga scala.
  • Controlla il feedback: Presta attenzione al feedback fornito dallo script per forzare GPUpdate da remoto dopo l’esecuzione per individuare tempestivamente eventuali problemi.
  • Effettua audit regolari: Verifica periodicamente i criteri per garantirne la rilevanza e l’efficacia.

Considerazioni finali

Nel contesto della gestione dei Criteri di gruppo, NinjaOne offre strumenti che integrano gli script PowerShell, fornendo una piattaforma integrata per una gestione IT più completa. Abbinando script come quello descritto per forzare GPUpdate da remoto alle solide funzionalità di gestione di NinjaOne, i professionisti IT possono ottenere maggiori controllo, efficienza e sicurezza nei loro ambienti di rete.

Passi successivi

La creazione di un team IT efficiente ed efficace richiede una soluzione centralizzata che funga da principale strumento per la fornitura di servizi. NinjaOne consente ai team IT di monitorare, gestire, proteggere e supportare tutti i dispositivi, ovunque essi si trovino, senza la necessità di una complessa infrastruttura locale.

Per saperne di più su NinjaOne Endpoint Management, fai un tour dal vivo, o inizia la tua prova gratuita della piattaforma NinjaOne.

Ti potrebbe interessare anche

Termini e condizioni NinjaOne

Cliccando sul pulsante “Accetto” qui sotto, dichiari di accettare i seguenti termini legali e le nostre condizioni d’uso:

  • Diritti di proprietà: NinjaOne possiede e continuerà a possedere tutti i diritti, i titoli e gli interessi relativi allo script (compreso il copyright). NinjaOne ti concede una licenza limitata per l’utilizzo dello script in conformità con i presenti termini legali.
  • Limitazione d’uso: Puoi utilizzare lo script solo per legittimi scopi personali o aziendali interni e non puoi condividere lo script con altri soggetti.
  • Divieto di ripubblicazione: In nessun caso ti è consentito ripubblicare lo script in una libreria di script appartenente o sotto il controllo di un altro fornitore di software.
  • Esclusione di garanzia: Lo script viene fornito “così com’è” e “come disponibile”, senza garanzie di alcun tipo. NinjaOne non promette né garantisce che lo script sia privo di difetti o che soddisfi le tue esigenze o aspettative specifiche.
  • Assunzione del rischio: L’uso che farai dello script è da intendersi a tuo rischio. Riconosci che l’utilizzo dello script comporta alcuni rischi intrinseci, che comprendi e sei pronto ad assumerti.
  • Rinuncia e liberatoria: Non riterrai NinjaOne responsabile di eventuali conseguenze negative o indesiderate derivanti dall’uso dello script e rinuncerai a qualsiasi diritto legale o di equità e a qualsiasi rivalsa nei confronti di NinjaOne in relazione all’uso dello script.
  • EULA: Se sei un cliente NinjaOne, l’uso dello script è soggetto al Contratto di licenza con l’utente finale (EULA) applicabile.