Eliminar la configuración de directiva obsoleta después de una actualización

Last published : Nov 13, 2026
Cuando Citrix® deja de usar un componente de producto, su configuración de directiva asociada deja de ser válida. Utilice GpoClean.ps1 para identificar y eliminar esta configuración obsoleta de las directivas de Citrix Virtual Apps and Desktops™ después de una actualización, incluidas las directivas que queden vacías como resultado.

Antes de empezar

Asegúrese de cumplir estos requisitos antes de ejecutar el script:
  • Una versión compatible de Citrix Virtual Apps and Desktops con Broker SDK y Group Policy Management instalados
  • Permisos de administración de directivas de Citrix en un Delivery Controller™
Nota:
El script carga automáticamente los complementos Citrix.Broker.Admin.V2 y Citrix.Common.GroupPolicy.

Eliminar la configuración de directiva obsoleta

Ejecute GpoClean.ps1 para eliminar la configuración de directiva obsoleta:
  1. Copie GpoClean.ps1 en un Delivery Controller en el que tenga permisos de administración de directivas de Citrix.
  2. Abra una sesión de PowerShell en el Delivery Controller.
  3. Ejecute el script. No se requieren parámetros.
    .\GpoClean.ps1
    Nota:
    Agregue -Verbose para un registro detallado por configuración: .\GpoClean.ps1 -Verbose.
El script se ejecuta en dos fases:
Fase Qué sucede
Fase 1 Ejecuta Test-BrokerDesktopPolicy, identifica errores de DeprecatedSetting y establece cada configuración afectada en NotConfigured
Fase 2 Vuelve a ejecutar Test-BrokerDesktopPolicy, identifica las directivas sin configuraciones (PolicyHasNoSettings) y las elimina
Todos los cambios se guardan en una única operación de escritura. Un resumen informa del número de configuraciones y directivas eliminadas. Si no se encuentran configuraciones obsoletas, el script finaliza sin cambios.
Nota:
  • La directiva Unfiltered nunca se elimina, incluso si no contiene ninguna configuración.

Script

Guarde el siguiente contenido como GpoClean.ps1 y, a continuación, ejecútelo como se describe en Eliminar configuraciones de directiva 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

Contenido relacionado

Para obtener más información sobre las configuraciones obsoletas en cada versión, consulte Cambios en las directivas.