Functions/Client/Watch-CdsAsynchOperation.ps1

<#
    .SYNOPSIS
    Monitor async operation completion.
#>

function Watch-CdsAsynchOperation {
    [CmdletBinding()]
    param
    (  
        [Parameter(Mandatory=$false, ValueFromPipeline)]
        [Microsoft.Xrm.Tooling.Connector.CrmServiceClient]
        $CdsClient = $Global:CdsClient,

        [Parameter(Mandatory, ValueFromPipeline)]
        [Guid]
        $AsyncOperationId,

        [Parameter(Mandatory=$false)]
        [int]
        $PollingIntervalSeconds = 5,
            
        [Parameter(Mandatory = $false)]
        [scriptblock] 
        $ScriptBlock
    )
    begin {   
        $StopWatch = [System.Diagnostics.Stopwatch]::StartNew(); 
        Trace-CdsFunction -Name $MyInvocation.MyCommand.Name -Stage Start -Parameters ($MyInvocation.MyCommand.Parameters); 
    }    
    process {

        $retryCount = 0;
        $maxRetries = 10;
        $completedStatusValue = @(30, 31, 32);
        $completed = $false;
        
        while(-not $completed)
        {
            Start-Sleep -Seconds $PollingIntervalSeconds;
            try {
                $asynchOperation = $CdsClient | Get-CdsRecord -LogicalName "asyncoperation" -Id $AsyncOperationId -Columns "statuscode", "message", "friendlymessage";                
            }
            catch {
                $retryCount++;
                if($retryCount -ge $maxRetries)
                {
                    throw "Asynch operation '$AsyncOperationId' not found!"
                }
            }            
            if($PSBoundParameters.ScriptBlock)
            {
                Invoke-Command -ScriptBlock $ScriptBlock -ArgumentList $asynchOperation;
            }

            $completed = $completedStatusValue.Contains($asynchOperation.statuscode_value.Value);
            if(-not $completed)
            {
                $completed = (-not [string]::IsNullOrWhiteSpace($asynchOperation.friendlymessage));
            }
        }
    }
    end {
        $StopWatch.Stop();
        Trace-CdsFunction -Name $MyInvocation.MyCommand.Name -Stage Stop -StopWatch $StopWatch;
    }    
}

Export-ModuleMember -Function Watch-CdsAsynchOperation -Alias *;