Remover configurações de política obsoletas após uma atualização

Last published : Nov 13, 2026
Quando a Citrix® descontinua um componente de produto, suas configurações de política associadas tornam-se inválidas. Use GpoClean.ps1 para identificar e remover essas configurações obsoletas das políticas do Citrix Virtual Apps and Desktops™ após uma atualização, incluindo quaisquer políticas que se tornem vazias como resultado.

Antes de começar

Certifique-se de atender a estes requisitos antes de executar o script:
  • Uma versão compatível do Citrix Virtual Apps and Desktops com Broker SDK e Gerenciamento de Política de Grupo instalados
  • Permissões de administração de política Citrix em um Delivery Controller™
Observação:
O script carrega automaticamente os snap-ins Citrix.Broker.Admin.V2 e Citrix.Common.GroupPolicy.

Remover configurações de política obsoletas

Execute GpoClean.ps1 para remover configurações de política obsoletas:
  1. Copie GpoClean.ps1 para um Delivery Controller no qual você tenha permissões de administração de política Citrix.
  2. Abra uma sessão do PowerShell no Delivery Controller.
  3. Execute o script. Nenhum parâmetro é necessário.
    .\GpoClean.ps1
    Observação:
    Adicione -Verbose para registro detalhado por configuração: .\GpoClean.ps1 -Verbose.
O script é executado em duas fases:
Fase O que acontece
Fase 1 Executa Test-BrokerDesktopPolicy, identifica DeprecatedSetting erros e define cada configuração afetada como NotConfigured
Fase 2 Reexecuta Test-BrokerDesktopPolicy, identifica políticas sem configurações definidas (PolicyHasNoSettings) e as remove
Todas as alterações são salvas em uma única operação de gravação. Um resumo relata o número de configurações e políticas removidas. Se nenhuma configuração obsoleta for encontrada, o script é encerrado sem alterações.
Observação:
  • A política Unfiltered nunca é removida, mesmo que não contenha configurações definidas.

Script

Salve o seguinte conteúdo como GpoClean.ps1, em seguida, execute-o conforme descrito em Remover configurações de política obsoletas:
<#
.Synopsis

    Cleans up deprecated settings from Citrix policies and removes policies that no longer have any settings.

.Description

    This script runs Test-BrokerDesktopPolicy to identify deprecated settings in policies. When a setting is
    deprecated (DeprecatedSetting error), the script removes the setting from the policy using the Citrix Group Policy
    PowerShell Provider. After removing deprecated settings, if a policy has no settings remaining
    (PolicyHasNoSettings error), the policy is removed automatically, except for the 'Unfiltered' policy which is
    preserved.

    This script is useful for cleaning up policies after upgrading to a newer version where some settings have been
    deprecated.

.Requirements

    Run this script on a DDC that has the Citrix Group Policy Management and Citrix Broker SDK installed.
#>

[CmdletBinding()]
param()

Write-Host "Checking Citrix policies for deprecated settings..."

# Load the Citrix Broker PowerShell Snapin.
$BrokerSnapin = "Citrix.Broker.Admin.V2"
$loaded = Get-PSSnapin $BrokerSnapin -ErrorAction SilentlyContinue
if ($loaded -eq $null)
{
    Add-PSSnapin $BrokerSnapin
}

# First pass: Run Test-BrokerDesktopPolicy to check for errors.
Write-Host "Running policy validation..."
$testResults = Test-BrokerDesktopPolicy | Select-Object -Property *

if ($testResults -eq $null -or $testResults.Count -eq 0)
{
    Write-Host "No policy errors found. All policies are clean."
    exit 0
}

# Check if there are any DeprecatedSetting errors.
$hasDeprecatedSettings = $false
foreach ($result in $testResults)
{
    if ([string]$result.ErrorCode -eq 'DeprecatedSetting')
    {
        $hasDeprecatedSettings = $true
        break
    }
}

if (-not $hasDeprecatedSettings)
{
    Write-Host "No deprecated settings found. Policy errors exist but do not require cleaning."
    Write-Host "Run 'Test-BrokerDesktopPolicy' to see other policy issues."
    exit 0
}

# Load the Citrix Group Policy PowerShell Provider (only if we need to clean).
Write-Host "`nDeprecated settings found. Loading Group Policy provider for cleanup..."
$GpSnapin = "Citrix.Common.GroupPolicy"
$Provider = "CitrixGroupPolicy"
$SiteName = "CitrixGP"

$loaded = Get-PSSnapin $GpSnapin -ErrorAction SilentlyContinue
if ($loaded -eq $null)
{
    Add-PSSnapin $GpSnapin
}

# Mount the provider drive if it has not been mounted.
$GpDrive = Get-PSDrive $SiteName -ErrorAction SilentlyContinue
if ($GpDrive -eq $null)
{
    [void]($GpDrive = New-PSDrive -PSProvider $Provider -Name $SiteName -Root \ -Controller localhost)
}

$uRoot = $SiteName + ":\User\"
$cRoot = $SiteName + ":\Computer\"

$GpDrive.AutoWriteBack = $false

$settingsRemoved = 0
$policiesRemoved = 0

$settingNameMappings = @{
    'PvsIntegrationEnabled' = 'ImageProviderIntegrationEnabled'
}

function Remove-SettingFromPolicy
{
    param(
        [string] $policyName,
        [string] $settingName
    )

    $targetSettingName = Split-Path -Path $settingName -Leaf

    if ($settingNameMappings.ContainsKey($targetSettingName))
    {
        $mappedSettingName = $settingNameMappings[$targetSettingName]
        Write-Verbose "Mapping deprecated setting name '$targetSettingName' to '$mappedSettingName'"
        $targetSettingName = $mappedSettingName
    }

    $searchPattern = $SiteName + ":\" + "*\" + $policyName + "\Settings\*"
    Write-Verbose "Searching for settings matching '$targetSettingName' in policy '$policyName'..."
    $allSettings = Get-ChildItem -Path $searchPattern -Recurse -ErrorAction SilentlyContinue |
        Where-Object {
            ($_.PSObject.Properties['State'] -and $_.State -ne 'NotConfigured') -or
            ($_.Name -eq 'Values' -and $_.Values -ne $null -and $_.Values -ne '')
        }

    $found = $false
    foreach ($setting in $allSettings)
    {
        $RootPath = "{0}\{1}::{2}:" -f $GpSnapin, $Provider, $SiteName
        $relativePath = $setting.PSPath.Substring($RootPath.Length)
        Write-Verbose "  Checking configured setting: $relativePath"
        $currentSettingName = Split-Path -Path $setting.PSPath -Leaf
        if ($currentSettingName -ne $targetSettingName) { continue }
        Write-Verbose "  Found matching setting: $relativePath"
        Set-ItemProperty -Path $setting.PSPath -Name State -Value NotConfigured
        Write-Host "  Set setting '$relativePath' to NotConfigured"
        $Script:settingsRemoved++
        $found = $true
    }

    if (-not $found)
    {
        Write-Warning "Could not find setting '$targetSettingName' in policy '$policyName'"
    }
}

function Remove-PolicyByName
{
    param(
        [string] $policyName
    )

    if ($policyName -eq 'Unfiltered')
    {
        Write-Host "  Skipping removal of 'Unfiltered' policy (reserved policy)"
        return
    }

    $uPath = $uRoot + $policyName
    $cPath = $cRoot + $policyName

    if (Test-Path $uPath)
    {
        $uSettings = Get-ChildItem -Path ($uPath + "\Settings") -Recurse -ErrorAction SilentlyContinue |
            Where-Object {
                ($_.PSObject.Properties['State'] -and $_.State -ne 'NotConfigured') -or
                ($_.Name -eq 'Values' -and $_.Values -ne $null -and $_.Values -ne '')
            }
        if ($uSettings.Count -eq 0)
        {
            Remove-Item -Path $uPath -Force -Recurse
            Write-Host "  Removed policy: \User\$policyName"
            $Script:policiesRemoved++
        }
    }

    if (Test-Path $cPath)
    {
        $cSettings = Get-ChildItem -Path ($cPath + "\Settings") -Recurse -ErrorAction SilentlyContinue |
            Where-Object {
                ($_.PSObject.Properties['State'] -and $_.State -ne 'NotConfigured') -or
                ($_.Name -eq 'Values' -and $_.Values -ne $null -and $_.Values -ne '')
            }
        if ($cSettings.Count -eq 0)
        {
            Remove-Item -Path $cPath -Force -Recurse
            Write-Host "  Removed policy: \Computer\$policyName"
            $Script:policiesRemoved++
        }
    }
}

# Phase 1: Remove deprecated settings.
Write-Host "`nPhase 1: Removing deprecated settings (this may take some time)..."
foreach ($result in $testResults)
{
    if ([string]$result.ErrorCode -eq 'DeprecatedSetting')
    {
        Write-Host "`nPolicy '$($result.PolicyName)' has deprecated settings:"
        if ($result.Settings -ne $null)
        {
            foreach ($setting in $result.Settings)
            {
                Write-Host "  - Setting '$($setting.SettingName)' is deprecated"
                Remove-SettingFromPolicy -policyName $result.PolicyName -settingName $setting.SettingName
            }
        }
    }
}

# Phase 2: Remove empty policies.
Write-Host "`nPhase 2: Checking for policies with no settings..."
$testResults2 = Test-BrokerDesktopPolicy | Select-Object -Property *

if ($testResults2 -eq $null -or $testResults2.Count -eq 0)
{
    Write-Host "No policy errors found."
}
else
{
    foreach ($result in $testResults2)
    {
        if ([string]$result.ErrorCode -eq 'PolicyHasNoSettings')
        {
            Write-Host "`nPolicy '$($result.PolicyName)' has no settings remaining:"
            Remove-PolicyByName -policyName $result.PolicyName
        }
    }
}

# Save all changes.
if ($settingsRemoved -gt 0 -or $policiesRemoved -gt 0)
{
    Write-Host "`nSaving changes..."
    $GpDrive.Save()
}

Remove-PSDrive $SiteName

Write-Host "`n=========================================="
Write-Host "Policy Cleanup Summary:"
Write-Host "  Settings removed: $settingsRemoved"
Write-Host "  Policies removed: $policiesRemoved"
Write-Host "=========================================="

if ($settingsRemoved -eq 0 -and $policiesRemoved -eq 0)
{
    Write-Host "`nNo issues found. All policies are clean."
}
else
{
    Write-Host "`nCleanup completed successfully."
}

exit 0

Conteúdo relacionado

Para obter mais informações sobre configurações obsoletas em cada versão, consulte Alterações de política.