[CmdletBinding(SupportsShouldProcess = $true)] param( [Parameter(Mandatory = $true)] [string]$SiteUrl, [Parameter(Mandatory = $true)] [string]$ListTitle, [Parameter(Mandatory = $true)] [string]$ExpiryFieldInternalName, [Guid]$FieldCustomizerComponentId = 'a555f4fc-d6a6-4421-8189-457449d9bbde', [switch]$RemoveClassicWebScriptLink ) $isapiPath = Join-Path ([Environment]::GetFolderPath('CommonProgramFiles')) 'microsoft shared\Web Server Extensions\16\ISAPI' Add-Type -Path (Join-Path $isapiPath 'Microsoft.SharePoint.Client.Runtime.dll') Add-Type -Path (Join-Path $isapiPath 'Microsoft.SharePoint.Client.dll') function Expand-ExpiryIndicatorBindings { param([object]$Value) if ($null -eq $Value) { return } if ($Value -is [System.Array]) { foreach ($item in $Value) { Expand-ExpiryIndicatorBindings -Value $item } return } if ($Value.PSObject.Properties['webUrl'] -and $Value.PSObject.Properties['listId'] -and $Value.PSObject.Properties['fieldInternalName']) { Write-Output $Value } } $context = New-Object Microsoft.SharePoint.Client.ClientContext($SiteUrl) $context.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials try { $list = $context.Web.Lists.GetByTitle($ListTitle) $field = $list.Fields.GetByInternalNameOrTitle($ExpiryFieldInternalName) $rootWeb = $context.Site.RootWeb $customActions = $list.UserCustomActions $webCustomActions = $context.Web.UserCustomActions $context.Load($list) $context.Load($field) $context.Load($context.Web) $context.Load($rootWeb) $context.Load($rootWeb.AllProperties) $context.Load($customActions) $context.Load($webCustomActions) $context.ExecuteQuery() if ($field.ClientSideComponentId -ne $FieldCustomizerComponentId) { throw "Das Feld '$($field.InternalName)' ist nicht mit dem erwarteten ExpiryIndicator-Field-Customizer verbunden." } if ($PSCmdlet.ShouldProcess("$($list.Title)/$($field.InternalName)", 'Field-Customizer-Verknüpfung entfernen')) { $field.ClientSideComponentId = [Guid]::Empty $field.ClientSideComponentProperties = '' $field.Update() $bindingsKey = 'PortalSettings.ExpiryIndicator.Bindings' $bindings = @() $existingBindingsJson = [string]$rootWeb.AllProperties[$bindingsKey] if (-not [string]::IsNullOrWhiteSpace($existingBindingsJson)) { try { $parsedBindings = $existingBindingsJson | ConvertFrom-Json $bindings = @(Expand-ExpiryIndicatorBindings -Value $parsedBindings) } catch { $bindings = @() } } $webUrl = $context.Web.Url.TrimEnd('/') $listId = $list.Id.ToString('D') $bindings = @($bindings | Where-Object { -not ( ([string]$_.webUrl).TrimEnd('/').Equals($webUrl, [StringComparison]::OrdinalIgnoreCase) -and ([string]$_.listId).Equals($listId, [StringComparison]::OrdinalIgnoreCase) ) }) $rootWeb.AllProperties[$bindingsKey] = (ConvertTo-Json -InputObject @($bindings) -Compress -Depth 5) $rootWeb.Update() $customActions | Where-Object { $_.Name -eq 'ExpiryIndicator.Classic.ScriptLink' -or $_.Name -eq 'ExpiryIndicator.Classic.Ribbon' } | ForEach-Object { $_.DeleteObject() } if ($RemoveClassicWebScriptLink) { $webCustomActions | Where-Object { $_.Name -eq 'ExpiryIndicator.Classic.ScriptLink' } | ForEach-Object { $_.DeleteObject() } } $context.ExecuteQuery() Write-Host 'ExpiryIndicator-Verknüpfung und listenspezifische Classic-Registrierungen wurden entfernt. Feld und Daten bleiben unverändert.' if (-not $RemoveClassicWebScriptLink) { Write-Host 'Der gemeinsam verwendete Classic-Web-ScriptLink bleibt bestehen. Verwende -RemoveClassicWebScriptLink, wenn keine weitere Liste ihn benötigt.' } } } finally { $context.Dispose() }