Private/ActivateFlows.ps1

function Invoke-FlowActivation {
    Param(
        [Microsoft.Xrm.Tooling.Connector.CrmServiceClient] $CRMConn,
        [string] [Parameter(Mandatory = $true)] $PipelinePath,
        [bool] [Parameter(Mandatory = $false)] $RunLocally = $false
    )

    Write-Host "Checking if there are Flows that need to be activated"
    if ($Deploy.Flows.ActivateFlows -eq $true) {
        if ($Deploy.Flows.OverrideFile) {
            Write-Host "Using $($Deploy.Flows.OverrideFile) for Flow activation"
            try {
                $FlowsToActivate = Get-Content -Path $PipelinePath\$SolutionFolder\$($Deploy.Flows.OverrideFile) -ErrorAction SilentlyContinue | ConvertFrom-Json    
            }
            catch {
                Write-PPDOMessage "$($_.Exception.Message)" -Type error -RunLocally $RunLocally 
            }
                                
        }
        else {
            Write-Host "Using Flows_Default.json for Flow activation"
            try {
                $FlowsToActivate = Get-Content -Path $PipelinePath\$SolutionFolder\Flows_Default.json -ErrorAction SilentlyContinue | ConvertFrom-Json 
            }
            catch {
                $FlowsToActivate = $null
            }                                
        }
        Write-Host "There are $($FlowsToActivate.Count) Flows that need activating"
        $ErrorCount = 0
        if ($FlowsToActivate.Count -gt 0) {
            $FlowsToActivate | ForEach-Object {
                $FlowStore = $_
                try {    
                    $workflow = Get-CrmRecord -conn $CRMConn -EntityLogicalName workflow -Id $_.FlowId -Fields clientdata, category, statecode, name
                                    
                    if ($_.ActivateAsUser) {
                        Write-Host "ActivateAsUser defined and set to: $($_.ActivateAsUser), attempting to Active Flow as this user"
                        $systemuserResult = Get-CrmRecords -conn $CRMConn -EntityLogicalName systemuser -FilterAttribute "domainname" -FilterOperator "eq" -FilterValue $_.ActivateAsUser
                        if ($systemuserResult.Count -gt 0) {
                            $systemUserId = $systemuserResult.CrmRecords[0].systemuserid
                            # Activate the workflow using the owner
                            if ($workflow.statecode -ne "Activated") {
                                $impersonationConn = $CRMConn
                                $impersonationCallerId = $systemUserId
                                $impersonationConn.OrganizationWebProxyClient.CallerId = $impersonationCallerId 
                                Write-PPDOMessage "Enabling Flow '$($workflow.name)'" -Type command -RunLocally $RunLocally
                                try {
                                    Set-CrmRecordState -conn $impersonationConn -EntityLogicalName workflow -Id $_.FlowId -StateCode Activated -StatusCode Activated    
                                }
                                catch {
                                    Write-PPDOMessage "There was an error activating the Flow, please confirm that the user exists and that the appropriate connections have been created as this user in the Environment" -Type warning -RunLocally $RunLocally -LogWarning $true
                                    Write-Host $_
                                    if ($_.ToString().Contains("ChildFlowNeverPublished")) {
                                        $FlowsToRetry += $FlowStore
                                    }
                                    else {
                                        $ErrorCount++    
                                    }
                                }       
                            }    
                        }
                        Write-PPDOMessage "User $($_.ActivateAsUser) was not found in $($Deploy.EnvironmentName)" -Type warning -RunLocally $RunLocally -LogWarning $true
                    }
                    else {
                        Write-Host "Checking if '$($workflow.name)' needs Activating..."
                        $solutions = Get-CrmRecords -conn $CRMConn -EntityLogicalName solution -FilterAttribute "uniquename" -FilterOperator "eq" -FilterValue "$($package.SolutionName)"
                        $solutionId = $solutions.CrmRecords[0].solutionid
                        $connRefs = (Get-CrmRecords -conn $CRMConn -EntityLogicalName connectionreference -FilterAttribute "solutionid" -FilterOperator eq -FilterValue $solutionid -Fields connectionreferencelogicalname, connectionid, connectorid, connectionreferenceid).CrmRecords
                        $connRefToUse = $connRefs | Where-Object { $null -ne $_.connectionid } | Select-Object -First 1 -ErrorAction SilentlyContinue
                        if ($null -ne $connRefToUse) {
                            Write-Host "---- Connection Ref Details ----"
                            Write-Host "Connection ID : " $connRefToUse.ConnectionId 
                            Write-Host $connRefToUse
                            Write-Host "--------------------------------"
                            $connection = Get-AdminPowerAppConnection -EnvironmentName $EnvId -Filter $connRefToUse.ConnectionId    
                        } 
                        else {
                            Write-PPDOMessage "There was an error getting a Connection to use, please confirm that the user exists and that the appropriate connections have been created as this user in the Environment" -Type warning -RunLocally $RunLocally -LogWarning $true
                            $ErrorCount++
                        }                                           
                        # Get Dataverse systemuserid for the system user that maps to the aad user guid that created the connection
                        if ($null -ne $connection) {
                            Write-Host "---- Connection Details -----"
                            Write-Host "Connection UserID : " $connection[0].CreatedBy.id
                            Write-Host $connection[0]
                            Write-Host "-----------------------------"
                            $systemusers = Get-CrmRecords -conn $CRMConn -EntityLogicalName systemuser -FilterAttribute "azureactivedirectoryobjectid" -FilterOperator "eq" -FilterValue $connection[0].CreatedBy.id
                        }                
                        else {
                            Write-PPDOMessage "There was an error getting the owner of the Connection to use, please confirm that the user exists and that the appropriate connections have been created as this user in the Environment" -Type warning -RunLocally $RunLocally -LogWarning $true
                            $ErrorCount++
                        }                            
                        if ($systemusers.Count -gt 0) {
                            # Impersonate the Dataverse systemuser that created the connection when updating the connection reference
                            $impersonationCallerId = $systemusers.CrmRecords[0].systemuserid
                            if ($workflow.statecode -ne "Activated") {
                                Write-PPDOMessage "Enabling Flow '$($workflow.name)' as Owner of Connection Reference" -Type command -RunLocally $RunLocally
                                $impersonationConn = $CRMConn
                                $impersonationConn.OrganizationWebProxyClient.CallerId = $impersonationCallerId 
                                try {
                                    Set-CrmRecordState -conn $impersonationConn -EntityLogicalName workflow -Id $_.FlowId -StateCode Activated -StatusCode Activated    
                                    Write-Host "...Activated" -ForegroundColor Green
                                }
                                catch {
                                    Write-PPDOMessage "There was an error activating the Flow, please confirm that the user exists and that the appropriate connections have been created as this user in the Environment" -Type warning -RunLocally $RunLocally -LogWarning $true
                                    Write-Host $_
                                    if ($_.ToString().Contains("ChildFlowNeverPublished")) {
                                        $FlowsToRetry += $FlowStore
                                    }
                                    else {
                                        $ErrorCount++    
                                    }
                                }
                            }
                        }                                          
                    }
                }
                catch {
                    # Catch in case the Get-CrmRecord returns null exception
                    Write-PPDOMessage "$($_.Exception.Message)" -Type error -RunLocally $RunLocally
                }
            }  
        }
        ########################## - Retry Flow
        $FlowsToRetry | ForEach-Object {
            Write-Host
            Write-Host "Retrying Flows that failed due to Child Flows" -ForegroundColor Green
            $workflow = Get-CrmRecord -conn $CRMConn -EntityLogicalName workflow -Id $_.FlowId -Fields clientdata, category, statecode, name
            if ($_.ActivateAsUser) {
                Write-Host "ActivateAsUser defined and set to : $($_.ActivateAsUser), attempting to Active Flow as this user"
                $systemuserResult = Get-CrmRecords -conn $CRMConn -EntityLogicalName systemuser -FilterAttribute "domainname" -FilterOperator "eq" -FilterValue $_.ActivateAsUser
                if ($systemuserResult.Count -gt 0) {
                    $systemUserId = $systemuserResult.CrmRecords[0].systemuserid
                    #Activate the workflow using the owner.
                    if ($workflow.statecode -ne "Activated") {
                        $impersonationConn = $CRMConn
                        $impersonationCallerId = $systemUserId
                        $impersonationConn.OrganizationWebProxyClient.CallerId = $impersonationCallerId 
                        Write-PPDOMessage "Enabling Flow '$($workflow.name)'" -Type command -RunLocally $RunLocally
                        try {
                            Set-CrmRecordState -conn $impersonationConn -EntityLogicalName workflow -Id $_.FlowId -StateCode Activated -StatusCode Activated    
                        }
                        catch {
                            Write-PPDOMessage "There was an error activating the Flow, please confirm that the user exists and that the appropriate connections have been created as this user in the Environment" -Type warning -RunLocally $RunLocally -LogWarning $true
                            Write-Host $_
                            $ErrorCount++    
                        }
                    }    
                }
                Write-PPDOMessage "User $($_.ActivateAsUser) was not found in $($Deploy.EnvironmentName)" -Type warning -RunLocally $RunLocally -LogWarning $true
            }
            else {
                Write-Host "Checking if '$($workflow.name)' needs Activating..."
                                    
                $solutions = Get-CrmRecords -conn $CRMConn -EntityLogicalName solution -FilterAttribute "uniquename" -FilterOperator "eq" -FilterValue "$($package.SolutionName)"
                $solutionId = $solutions.CrmRecords[0].solutionid
                $connRefs = (Get-CrmRecords -conn $CRMConn -EntityLogicalName connectionreference -FilterAttribute "solutionid" -FilterOperator eq -FilterValue $solutionid -Fields connectionreferencelogicalname, connectionid, connectorid, connectionreferenceid).CrmRecords
                $connRefToUse = $connRefs | Where-Object { $null -ne $_.connectionid } | Select-Object -First 1 -ErrorAction SilentlyContinue
                $connection = Get-AdminPowerAppConnection -EnvironmentName $EnvId -Filter $connRefToUse.ConnectionId
                # Get Dataverse systemuserid for the system user that maps to the aad user guid that created the connection
                $systemusers = Get-CrmRecords -conn $CRMConn -EntityLogicalName systemuser -FilterAttribute "azureactivedirectoryobjectid" -FilterOperator "eq" -FilterValue $connection[0].CreatedBy.id
                if ($systemusers.Count -gt 0) {
                    # Impersonate the Dataverse systemuser that created the connection when updating the connection reference
                    $impersonationCallerId = $systemusers.CrmRecords[0].systemuserid
                    if ($workflow.statecode -ne "Activated") {
                        Write-PPDOMessage "Enabling Flow '$($workflow.name)' as Owner of Connection Reference" -Type command -RunLocally $RunLocally
                        $impersonationConn = $CRMConn
                        $impersonationConn.OrganizationWebProxyClient.CallerId = $impersonationCallerId 
                        try {
                            Set-CrmRecordState -conn $impersonationConn -EntityLogicalName workflow -Id $_.FlowId -StateCode Activated -StatusCode Activated    
                        }
                        catch {
                            Write-PPDOMessage "There was an error activating the Flow, please confirm that the user exists and that the appropriate connections have been created as this user in the Environment" -Type warning -RunLocally $RunLocally -LogWarning $true
                            Write-Host $_
                            $ErrorCount++    
                        }
                    }
                }               
            }
        }
        if ($Deploy.Flows.FailOnError -eq $true -and $ErrorCount -gt 0) {
            Write-PPDOMessage "There were $ErrorCount Flow activation errors and FailOnError is set to True... exiting." -Type error -RunLocally $RunLocally -LogError $true
            exit 1                     
        }
    }                                
    else {
        Write-Host "No Flows were specified for activation. If you wish to include flows for activation, please add the following in deployPackages.json
 
            ""Flows"":
            {
                ""ActivateFlows"": ""true"",
                ""OverrideFile"" : """",
                ""FailOnError"" : ""false""
            }"

    }
}