src/Plugins/Remove-XrmPluginAssembly.ps1
|
<# .SYNOPSIS Delete a plug-in assembly with its steps and plug-in types. .DESCRIPTION Delete the steps of the assembly (their images go with them), then its plug-in types, then the assembly itself. Without Force, raises an error when the assembly still has steps, and deletes nothing. Raises an error, before deleting anything, when the assembly is managed (remove it by uninstalling its solution) or does not exist. A plug-in type used by a custom API or a custom workflow activity cannot be deleted: the platform error is raised and the assembly is kept. .PARAMETER XrmClient Xrm connector initialized to target instance. Use latest one by default. (Dataverse ServiceClient) .PARAMETER Name Plug-in assembly name (pluginassembly.name, without version). .PARAMETER Force Delete the steps registered on the assembly first. .OUTPUTS PSCustomObject. AssemblyId, StepsRemoved, TypesRemoved. .EXAMPLE Remove-XrmPluginAssembly -XrmClient $xrmClient -Name "Contoso.Plugins.Legacy" -Force; .LINK https://github.com/AymericM78/PowerDataOps/blob/main/documentation/commands/Remove-XrmPluginAssembly.md #> function Remove-XrmPluginAssembly { [CmdletBinding(SupportsShouldProcess)] [OutputType([PSCustomObject])] param ( [Parameter(Mandatory = $false, ValueFromPipeline)] [Microsoft.PowerPlatform.Dataverse.Client.ServiceClient] $XrmClient = $Global:XrmClient, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $Name, [Parameter(Mandatory = $false)] [switch] $Force ) begin { $StopWatch = [System.Diagnostics.Stopwatch]::StartNew(); Trace-XrmFunction -Name $MyInvocation.MyCommand.Name -Stage Start -Parameters ($MyInvocation.MyCommand.Parameters); } process { $assembly = $XrmClient | Get-XrmRecord -LogicalName "pluginassembly" -AttributeName "name" -Value $Name -Columns "name", "ismanaged" -AsEntity; if (-not $assembly) { throw "Plug-in assembly '$Name' not found."; } if ($assembly["ismanaged"]) { throw "Plug-in assembly '$Name' is managed: uninstall its solution to remove it."; } $typeQuery = New-XrmQueryExpression -LogicalName "plugintype" -Columns "typename"; $typeQuery = $typeQuery | Add-XrmQueryCondition -Field "pluginassemblyid" -Condition Equal -Values $assembly.Id; $types = $XrmClient | Get-XrmMultipleRecords -Query $typeQuery -AsEntity -AsArray; $steps = @(); if ($types.Count -gt 0) { $stepQuery = New-XrmQueryExpression -LogicalName "sdkmessageprocessingstep" -Columns "name"; $stepQuery = $stepQuery | Add-XrmQueryCondition -Field "eventhandler" -Condition In -Values @($types | ForEach-Object { $_.Id }); $steps = $XrmClient | Get-XrmMultipleRecords -Query $stepQuery -AsEntity -AsArray; } if ($steps.Count -gt 0 -and -not $Force) { throw "Plug-in assembly '$Name' still has $($steps.Count) step(s): use -Force to delete them with the assembly."; } # Each deletion stops the process on failure: the assembly stays when a type cannot be deleted foreach ($step in $steps) { try { $XrmClient | Remove-XrmRecord -LogicalName "sdkmessageprocessingstep" -Id $step.Id -ErrorAction Stop; } catch { throw "Cannot delete step '$($step["name"])' of plug-in assembly '$Name': $($_.Exception.Message)"; } } foreach ($type in $types) { try { $XrmClient | Remove-XrmRecord -LogicalName "plugintype" -Id $type.Id -ErrorAction Stop; } catch { throw "Cannot delete plug-in type '$($type["typename"])' of plug-in assembly '$Name': $($_.Exception.Message)"; } } try { $XrmClient | Remove-XrmRecord -LogicalName "pluginassembly" -Id $assembly.Id -ErrorAction Stop; } catch { throw "Cannot delete plug-in assembly '$Name': $($_.Exception.Message)"; } if ($WhatIfPreference) { return; } [PSCustomObject]@{ AssemblyId = $assembly.Id; StepsRemoved = $steps.Count; TypesRemoved = $types.Count; }; } end { $StopWatch.Stop(); Trace-XrmFunction -Name $MyInvocation.MyCommand.Name -Stage Stop -StopWatch $StopWatch; } } Export-ModuleMember -Function Remove-XrmPluginAssembly -Alias *; |