src/Solutions/Layers/Get-XrmCustomizedSolutionComponents.ps1
|
<# .SYNOPSIS Get customized solution components from Active layer. .DESCRIPTION Retrieves solution components from a solution, then keeps only components with meaningful Active-layer customizations. .PARAMETER XrmClient Xrm connector initialized to target instance. Use latest one by default. (Dataverse ServiceClient) .PARAMETER SolutionUniqueName Unmanaged solution unique name where to inspect components. .PARAMETER ComponentTypes Solution component types to inspect. Default: inspect all component types in solution. .PARAMETER ExcludedProperties Changed properties to ignore when evaluating meaningful customizations. .PARAMETER IncludedProperties If provided, only these changed properties are evaluated. .PARAMETER IncludeDetails Include changed properties and layer metadata in output. .OUTPUTS PSCustomObject array. .EXAMPLE $components = Get-XrmCustomizedSolutionComponents -SolutionUniqueName "MySolution"; .EXAMPLE $components = Get-XrmCustomizedSolutionComponents -SolutionUniqueName "MySolution" -ComponentTypes @(60, 26) -IncludeDetails; #> function Get-XrmCustomizedSolutionComponents { [CmdletBinding()] [OutputType([PSCustomObject[]])] param ( [Parameter(Mandatory = $false, ValueFromPipeline)] [Microsoft.PowerPlatform.Dataverse.Client.ServiceClient] $XrmClient = $Global:XrmClient, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $SolutionUniqueName, [Parameter(Mandatory = $false)] [int[]] $ComponentTypes = @(), [Parameter(Mandatory = $false)] [String[]] $ExcludedProperties = @("displaymask", "createdon", "modifiedon", "attributetypeid", "attributelogicaltypeid"), [Parameter(Mandatory = $false)] [String[]] $IncludedProperties = @(), [Parameter(Mandatory = $false)] [switch] $IncludeDetails ) begin { $StopWatch = [System.Diagnostics.Stopwatch]::StartNew(); Trace-XrmFunction -Name $MyInvocation.MyCommand.Name -Stage Start -Parameters ($MyInvocation.MyCommand.Parameters); } process { $components = @($XrmClient | Get-XrmSolutionComponents -SolutionUniqueName $SolutionUniqueName -ComponentTypes $ComponentTypes); if ($components.Count -eq 0) { return @(); } [System.Collections.ArrayList]$customizedComponents = @(); ForEach-ObjectWithProgress -Collection $components -OperationName "Inspecting active-layer customizations for $SolutionUniqueName" -ScriptBlock { param($component) $componentId = [Guid]::Empty; $componentType = $null; try { if ($component.PSObject.Properties.Match("objectid").Count -gt 0 -and $component.objectid) { $componentId = [Guid]::Parse($component.objectid.ToString()); } else { return; } } catch { return; } if ($component.PSObject.Properties.Match("componenttype_Value").Count -gt 0 -and $component.componenttype_Value) { if ($component.componenttype_Value.PSObject.Properties.Match("Value").Count -gt 0) { $componentType = [int]$component.componenttype_Value.Value; } else { $componentType = [int]$component.componenttype_Value; } } elseif ($component.PSObject.Properties.Match("componenttype").Count -gt 0 -and $component.componenttype) { if ($component.componenttype -is [int]) { $componentType = [int]$component.componenttype; } elseif ($component.componenttype.PSObject.Properties.Match("Value").Count -gt 0) { $componentType = [int]$component.componenttype.Value; } } if ($null -eq $componentType) { return; } try { $componentTypeName = Get-XrmSolutionComponentName -SolutionComponentType $componentType; } catch { return; } $customizationCheck = $XrmClient | Test-XrmComponentCustomization ` -ComponentId $componentId ` -SolutionComponentName $componentTypeName ` -ExcludedProperties $ExcludedProperties ` -IncludedProperties $IncludedProperties ` -ReturnDetails:$IncludeDetails; $isCustomized = $false; if ($IncludeDetails) { $isCustomized = [bool]$customizationCheck.HasCustomization; } else { $isCustomized = [bool]$customizationCheck; } if (-not $isCustomized) { return; } if ($IncludeDetails) { $customizedComponent = [pscustomobject]@{ "ComponentId" = $componentId; "ComponentType" = $componentType; "ComponentTypeName" = $componentTypeName; "IsCustomized" = $true; "ChangedProperties" = $customizationCheck.ChangedProperties; "LayerId" = $customizationCheck.LayerId; }; $customizedComponents.Add($customizedComponent) | Out-Null; } else { $customizedComponent = [pscustomobject]@{ "ComponentId" = $componentId; "ComponentType" = $componentType; "ComponentTypeName" = $componentTypeName; "IsCustomized" = $true; }; $customizedComponents.Add($customizedComponent) | Out-Null; } }; $customizedComponents; } end { $StopWatch.Stop(); Trace-XrmFunction -Name $MyInvocation.MyCommand.Name -Stage Stop -StopWatch $StopWatch; } } Export-ModuleMember -Function Get-XrmCustomizedSolutionComponents -Alias *; Register-ArgumentCompleter -CommandName Get-XrmCustomizedSolutionComponents -ParameterName "SolutionUniqueName" -ScriptBlock { param($CommandName, $ParameterName, $WordToComplete, $CommandAst, $FakeBoundParameters) $solutionUniqueNames = @(); $solutions = Get-XrmSolutions -Columns "uniquename"; $solutions | ForEach-Object { $solutionUniqueNames += $_.uniquename; }; return $solutionUniqueNames | Where-Object { $_ -like "$wordToComplete*" } | Sort-Object; } |