The below example will demonstrate how to enable cloud flows in Dynamics 365 after a solution deployment using Azure DevOps Pipelines and Releases. I will be using an Application User for authentication.
[CmdletBinding()]
param(
[string]$tenantId,
[string]$applicationId,
[string]$clientSecret,
[string]$solutionName,
[string]$azureactivedirectoryobjectid
)
$url = $Env:url
$connectionString = "AuthType=ClientSecret;ClientId=$applicationId;ClientSecret=$clientSecret;Url=$url"
Write-Host "Starting Enabling Cloud Flows Power Shell Script..."
# Login to PowerApps for the Admin commands
Write-Host "Login to PowerApps for the Admin commands"
Install-Module Microsoft.PowerApps.Administration.PowerShell -RequiredVersion "2.0.105" -Force -Scope CurrentUser -AllowClobber
Add-PowerAppsAccount -TenantID $tenantId -ApplicationId $applicationId -ClientSecret $clientSecret -Endpoint "prod"
# Login to PowerApps for the Xrm.Data commands
Write-Host "Login to PowerApps for the Xrm.Data commands"
Install-Module Microsoft.Xrm.Data.PowerShell -RequiredVersion "2.8.14" -Force -Scope CurrentUser -AllowClobber
$conn = Get-CrmConnection -ConnectionString $connectionString
$user = Get-CrmRecords -conn $conn -EntityLogicalName systemuser -FilterAttribute azureactivedirectoryobjectid -FilterOperator eq -FilterValue $azureactivedirectoryobjectid
# Create a new Connection to impersonate the creator of the connection reference
$impersonatedconn = Get-CrmConnection -ConnectionString $connectionString
$impersonatedconn.OrganizationWebProxyClient.CallerId = $user.CrmRecords[0].systemuserid
$existingconnectionreferences = (ConvertTo-Json ($connectionsrefs | Select-Object -Property connectionreferenceid, connectionid)) -replace "`n|`r",""
Write-Host "##vso[task.setvariable variable=CONNECTION_REFS]$existingconnectionreferences"
Write-Host "Connection References:$existingconnectionreferences"
# Get the flows that are turned off
Write-Host "Get Flows that are turned off"
$fetchFlows = @"
<fetch>
<entity name='workflow' >
<attribute name='category' />
<attribute name='name' />
<attribute name='statecode' />
<attribute name='workflowid' />
<filter type='and' >
<condition attribute='category' operator='eq' value='5' />
<condition attribute='statecode' operator='eq' value='0' />
</filter>
<link-entity name='solutioncomponent' from='objectid' to='workflowid' >
<filter>
<condition attribute='solutionidname' operator='eq' value='$solutionName' />
</filter>
</link-entity>
</entity>
</fetch>
"@;
$flows = (Get-CrmRecordsByFetch -conn $conn -Fetch $fetchFlows -Verbose).CrmRecords
if ($flows.Count -eq 0)
{
Write-Host "##vso[task.logissue type=warning]No Flows that are turned off in $solutionName."
Write-Output "No Flows that are turned off"
exit(0)
}
# Turn on flows
foreach ($flow in $flows){
try {
Write-Output "Turning on Flow:$(($flow).name)"
Set-CrmRecordState -conn $impersonatedconn -EntityLogicalName workflow -Id $flow.workflowid -StateCode Activated -StatusCode Activated -Verbose -Debug
}
catch {
Write-Warning "An error occored when activating flow:$(($flow).name)"
Write-Warning $_
}
}
You will need to add the PowerShell script as a PowerShell task inside of the Releases Agent Job.
Variables
You will need to add your Application User connection details as Release Variables so they can be referenced in the PowerShell task.
Script Path
You can either reference the code inside of the published Artifiact or you can add the code directly to the task as an inline.
Arguments
You will also need to pass arguments inside of the task otherwise the PowerShell code wont know what these variables are:
-tenantId $(tenantId) -applicationId $(applicationId) -clientSecret $(clientSecret) -solutionName $(solutionName) -azureactivedirectoryobjectid $(azureactivedirectoryobjectid)
Environment Variables
You will also need to set what target environment url you will be checking against by adding an Environment Variable
Hi,
Do we have any way to modify the existing connection reference with connection (connection id) using PowerShell commands?
I am really struggling to find a solution to this scenario.
How to fix “Cannot bind argument to parameter ‘records’ because it is null.” when there are no records returned by the fetch xml?
Hi,
I don’t why it’s still using the SPN rather than impersonation as it complained the SPN cannot turn on the flow either because the shared connection is not a valid one or because it is not a connection you have access permission.
We are getting ‘cannot conver null to type “system.guid”.’
$impersonaredconn.oraganizationWebProxyClient.CallerID =$user.CrmRecords[0].systemuserid
Hi Harish,
Did you put in the correct guid for $azureactivedirectoryobjectid? This should be the azure activedirectory id of the Application User that you are using for the deployment
Thanks Thomas, i have changed the $azureactivedirectoryobjectid, Now
it’s working fine
is there any other way instead of client secret value we can use as user don’t want to provide secret?
Hi Yatish, I know that you can link an azure key vault or you can get the user to input the secret themselves and press the keypad lock to hide the value from users. Once the value is locked then no one else can see it again – https://learn.microsoft.com/en-us/azure/devops/pipelines/process/set-secret-variables?view=azure-devops&tabs=yaml%2Cbash
What is the purpose for the section regarding $existingconnectionreferences? This doesn’t seem to be related to the other actions in the script.