升级后移除已弃用的策略设置

Last published : Nov 13, 2026
当 Citrix® 弃用产品组件时,其关联的策略设置将失效。升级后,使用 GpoClean.ps1 从 Citrix Virtual Apps and Desktops™ 策略中识别并移除这些已弃用的设置,包括因此而变为空的任何策略。

开始之前

运行脚本前,请确保满足以下要求:
  • 已安装 Broker SDK 和 Group Policy Management 的受支持的 Citrix Virtual Apps and Desktops 版本
  • 在 Delivery Controller™ 上具有 Citrix 策略管理权限
注意:
脚本会自动加载 Citrix.Broker.Admin.V2 和 Citrix.Common.GroupPolicy 管理单元。

移除已弃用的策略设置

运行 GpoClean.ps1 以移除已弃用的策略设置:
  1. 将 GpoClean.ps1 复制到您具有 Citrix 策略管理权限的 Delivery Controller 上。
  2. 在 Delivery Controller 上打开 PowerShell 会话。
  3. 运行脚本。无需任何参数。
    .\GpoClean.ps1
    注意:
    添加 -Verbose 以获取详细的按设置日志记录:.\GpoClean.ps1 -Verbose。
脚本分两个阶段运行:
阶段 发生什么
阶段 1 运行 Test-BrokerDesktopPolicy,识别 DeprecatedSetting 错误,并将每个受影响的设置设为 NotConfigured
阶段 2 重新运行 Test-BrokerDesktopPolicy,识别没有配置设置的策略 (PolicyHasNoSettings),并将其删除
所有更改都保存在单个写入操作中。摘要报告已删除的设置和策略的数量。如果未找到任何已弃用的设置,脚本将退出且不进行任何更改。
注意:
  • Unfiltered 策略永远不会被删除,即使它不包含任何配置的设置。

脚本

将以下内容另存为 GpoClean.ps1,然后按照 删除已弃用的策略设置 中所述运行它:
<#
.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

相关内容

有关每个版本中已弃用设置的更多信息,请参阅 策略更改。