src/Solutions/Publish-XrmComponent.ps1
|
<# .SYNOPSIS Publish a specific Dataverse component using a targeted PublishXml request. .DESCRIPTION Publish one or several components of the same type (app module, entity, option set, web resource, ribbon, etc.) without triggering a full Publish-XrmCustomizations. Builds the required <importexportxml> payload from the component name and identifiers: one request for all of them. Use this instead of Publish-XrmCustomizations when you want to target a few components and avoid the overhead of a full publish cycle. .PARAMETER XrmClient Xrm connector initialized to target instance. Use latest one by default. (Dataverse ServiceClient) .PARAMETER ComponentName XML element name of the component type to publish. Common values: appmodule, entity, optionset, webresource, ribbon, sitemap, workflow. .PARAMETER ComponentId Identifiers of the components: GUID strings for record-based components (appmodule, webresource), logical names for schema-based components (entity, optionset, ribbon). .PARAMETER TimeoutInMinutes Maximum wait for the publish, which is synchronous. The request is sent through a clone of the connection created with this timeout (a ServiceClient keeps the timeout it was created with). (Default: the timeout of the connection) .OUTPUTS Microsoft.Xrm.Sdk.OrganizationResponse. Response from the PublishXml request. .EXAMPLE # Publish a model-driven app Publish-XrmComponent -ComponentName "appmodule" -ComponentId "3d9e2f1a-..."; .EXAMPLE # Publish a single entity's customizations Publish-XrmComponent -ComponentName "entity" -ComponentId "account"; .EXAMPLE # Publish several apps in one request, allowing 20 minutes Publish-XrmComponent -XrmClient $xrmClient -ComponentName "appmodule" -ComponentId $salesApp.Id, $serviceApp.Id -TimeoutInMinutes 20; .LINK https://github.com/AymericM78/PowerDataOps/blob/main/documentation/commands/Publish-XrmComponent.md #> function Publish-XrmComponent { [CmdletBinding(SupportsShouldProcess)] [OutputType([Microsoft.Xrm.Sdk.OrganizationResponse])] param ( [Parameter(Mandatory = $false, ValueFromPipeline)] [Microsoft.PowerPlatform.Dataverse.Client.ServiceClient] $XrmClient = $Global:XrmClient, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $ComponentName, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string[]] $ComponentId, [Parameter(Mandatory = $false)] [ValidateRange(1, 1440)] [int] $TimeoutInMinutes ) begin { $StopWatch = [System.Diagnostics.Stopwatch]::StartNew(); Trace-XrmFunction -Name $MyInvocation.MyCommand.Name -Stage Start -Parameters ($MyInvocation.MyCommand.Parameters); } process { $elements = ($ComponentId | ForEach-Object { "<${ComponentName}>$_</${ComponentName}>" }) -join ""; $xml = "<importexportxml><${ComponentName}s>$elements</${ComponentName}s></importexportxml>"; $request = New-XrmRequest -Name "PublishXml"; $request | Add-XrmRequestParameter -Name "ParameterXml" -Value $xml | Out-Null; if (-not $PSBoundParameters.ContainsKey('TimeoutInMinutes')) { return ($XrmClient | Invoke-XrmRequest -Request $request); } # The timeout of a ServiceClient is fixed when it connects: a clone made after raising the # static MaxConnectionTimeout gets the longer one, the caller's client keeps its own $previousTimeout = [Microsoft.PowerPlatform.Dataverse.Client.ServiceClient]::MaxConnectionTimeout; $publishClient = $null; try { [Microsoft.PowerPlatform.Dataverse.Client.ServiceClient]::MaxConnectionTimeout = [TimeSpan]::FromMinutes($TimeoutInMinutes); $publishClient = $XrmClient.Clone(); Invoke-XrmRequest -XrmClient $publishClient -Request $request; } finally { [Microsoft.PowerPlatform.Dataverse.Client.ServiceClient]::MaxConnectionTimeout = $previousTimeout; if ($publishClient) { $publishClient.Dispose(); } } } end { $StopWatch.Stop(); Trace-XrmFunction -Name $MyInvocation.MyCommand.Name -Stage Stop -StopWatch $StopWatch; } } Export-ModuleMember -Function Publish-XrmComponent -Alias *; |