Duplicated Workflows in Advance Find Dynamics 365

In this post I am going to share my recent experience with workflows in Dynamics 365.

When I search for the processes and look for the workflows in Advanced find then I got a little surprise that I am seeing multiple workflows with same name. This happened on all our working & testing environments too.

Then I started analyzing the same why it was like that. The First thing I observed (most Interesting thing) that was, there are only 2 Copies of them are in Active and all Other are in Draft Mode.

Still I continued my Investigation and collected more information from MS team about the same.

This is normal behavior for Dynamics 365. The ‘Process’ table, which holds the workflow records. What we are seeing are not duplicate workflows, but rather different versions of the same workflow. This is a standard feature of Dynamics 365 designed to maintain a history of changes to workflows. Each time a workflow is updated and imported, a new version is created and set to active, while the previous versions are set to draft.

For the two Activated workflow instances, one is for the workflow record itself and is of type Definition, while, the other instances are of type Activation. All Other are Draft versions of Previous Activation copy.

If the presence of these draft versions is causing confusion or clutter, they can be manually deleted from the system. Please be careful not to delete the active version of the workflow, as this is the most recent and operational version.

This clarifies the situation.

I hope this helps!

Generate New Client Secret for Azure Service Principal Using PS Script

In one of my recent assignments, I came across a situation where our existing Azure function app which is connecting to Share Point started failing with message {“Getting token failed with status: Unauthorized”}.

After detailed investigation, I found that we are using Azure AD service principal to connect to Share Point and it’s Client Secret for expired.

But I did not see any option to extend the expiration or to generate the new Key of Service Principal from the Azure AD portal.

I see an option to generate new key for App Registrations -> Application Registrations -> App -> Certificates & Secrets. This is not what we are looking.

This new secret Key generation for the Service Principal can be done using Azure PowerShell module.

I was able to generate the Key using the following script.

Pre-requisites: Azure PowerShell Module should be installed on the machine from where we are going to run this script.

#Connect to the Azure Account.
Connect-AzAccount

# Initialize service principal variable
$name = "ServicePrincipalName"

# Get service principal
$sp = Get-AzADServicePrincipal -DisplayName $name

$sp

# View current password Ids and expirations
Get-AzADSpCredential -DisplayName $name

#choose expiration date
$start = get-date
$end = $start.AddYears(5)

# Set new Credentails
$creds = [Microsoft.Azure.PowerShell.Cmdlets.Resources.MSGraph.Models.ApiV10.MicrosoftGraphPasswordCredential]@{
StartDateTime = $start
EndDateTime = $end
}

$spCreds = New-AzADSpCredential -PasswordCredentials $creds -ServicePrincipalName "IdOfServicePrincipal"

$spCreds

Calculate Review Date based on week or working days Calendar

In one of my recent assignment, I came across one requirement that we need to calculate Case Review Date based on Working Days Calendar.

I thought to address this requirement by creating one generic power automate to calculate date based on the week / working days calendar.

This PA can be called from any of other power automates and will return the final date.

I am providing the power automate steps in detail.

Step1: Overview of the Power automate.

Step2: Details of First Step “Manually Trigger a flow”

Step3: All required variables

Step4: Check condition for Week or Working Days Option.

Yes – Option

runningDate = addDays(variables(‘returnDate’),1)

returnDate = formatDateTime(variables(‘runningDate’), ‘yyyy-MM-dd’)

No – Option

returnDate = formatDateTime(addDays(triggerBody()[‘date’], variables(‘NoOfDays’)), ‘yyyy-MM-dd’)

Step5: Condition To Exclude Weekends

dayOfWeek(variables(‘returnDate’))

Yes – Option

Step6: Return final Date

I hope this help!

Calling Power Automate from Ribbon button

Calling Power Automate from Ribbon Button

In my recent assignment I got a requirement to call Power Automate from the Ribbon button.

To achieve this I have followed these minimal easy steps.

Note: This requirement is for Case Entity so we need to pass the CaseId to the Power Automate.

1. Created a Power Automate with Trigger point as “When an HTTP request received” and implemented all our required logic in next action steps.

2. Written a Java script file with following code and included that web resource.

In the below script “Helper.getConfigValue(“HTTP_POST_URL”)” is generic method which we implemented to get the Power Automate “HTTP_POST_URL” which we stored in config entity. (This URL you will get once after we save the Power Automate with Trigger as “When an HTTP request received“)

  static CallingPowerAutomate(formContext: Xrm.FormContext) {

            let flowUrl: string;
            Helper.getConfigValue("HTTP_POST_URL").then(
                result => {
                    if (result.entities.length > 0 && result.entities[0].value !== null) {
                        flowUrl = result.entities[0].value;
                    }
                    if (!flowUrl) {
                        Xrm.Navigation.openAlertDialog({ text: "No HTTP Power Automate URL has been configured." });
                        return;
                    }

                    try {
                            Xrm.Utility.showProgressIndicator("In progress.... Please do not close this window.");

                            var data = { "CaseId": "" };
                            data.CaseId = formContext.data.entity.getId().replace("{", "").replace("}", "");
                            var requestUrl = flowUrl;
                            var req = new XMLHttpRequest();
                            req.open("POST", requestUrl, true);
                            req.setRequestHeader("Accept", "application/json");
                            req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
                            req.setRequestHeader("OData-MaxVersion", "4.0");
                            req.setRequestHeader("OData-Version", "4.0");
                            req.onreadystatechange = function () {
                                if (this.readyState === 4 || this.readyState === 2) {
                                    req.onreadystatechange = null;
                                    if (this.status === 200) { //|| this.status === 202 || this.status === 204
                                        var alertStrings = { confirmButtonLabel: "Yes", text: "Process completed.", title: "Process Message" };
                                        var alertOptions = { height: 120, width: 260 };
                                        Xrm.Navigation.openAlertDialog(alertStrings, alertOptions);
                                        Xrm.Utility.closeProgressIndicator();
                                    }
                                    else if (this.status === 400) {
                                        var alertStrings = { confirmButtonLabel: "Yes", text: this.statusText.toString(), title: "Process Message" };
                                        var alertOptions = { height: 120, width: 260 };
                                        Xrm.Navigation.openAlertDialog(alertStrings, alertOptions);
                                        Xrm.Utility.closeProgressIndicator();
                                    }
                                    else {
                                        JSON.parse(this.response).error;
                                    }
                                }
                            };
                            req.send(JSON.stringify(data));
                        
                    }
                    catch (ex) {
                        Xrm.Navigation.openAlertDialog({ text: ex.message });
                    }
                });

        }

3. Add a Button on Form level using Ribbon Workbench.

4. Add a Command in which we can call this above JS method “CallingPowerAutomate” as part of Custom Javascript Action.

5. Update Button Command and Commandcore with above Command Name which we created.

6. Publish all these changes from Ribbon workbench.

Now the button get started appearing on the form and when we click on that button Power Automate flow runs and perform the required action.

Hope this Help!

Copy/Duplicate (SaveAs) a Flow with a Child flow in a Solution

In one of assignments this is one more scenario which I faced when I try to do “SaveAs” my existing Power Automate. I have one Child flow calling inside my Parent Flow. And I need to do the similar activity multiple times.

To overcome this problem and to make a exact copy of my existing flow, I have followed below technique and it solved my problem.

I have updated couple of xml and json files. Here are the steps I follwed.

  1. Created a Solution with my Power Automate.
  2. Exported the Unmanaged solution and did unzip.
  3. The unzip folder contains below files inside it.
    1. Workflows (folder)
      1. Workflow.Json
    2. [Content_Types].xml
    3. customizations.xml
    4. solution.xml
  4. I have Opened the Workflows folder and Replicated the Json file (which is Flow file).
  5. Renamed the new Json filed with name which I want to save. By providing the new GUID for the new Flow.
  6. As part of next steps I have opened “customizations.xml” and Replicate the Workflow Node which is present in that file.
  7. Update the GUID and Name of the flow for the new One.
  8. And Next Need to do some modification in “solution.xml”
  9. Open the “solution.xml” and replicate the Root Component in that and update the New GUID for the new component and save the files.
  10. Now Zip all these files.
  11. Import back the new Zip solution.

This created exact copy of my Flow in the solution and worked fine.

Hope this help!

Use of the WS-Trust (Office365) authentication security protocol when connecting to Microsoft Dataverse is no longer recommended

In one of my recent assignments, I came across this situation like my Azure function which we deployed to connect to our Dataverse throwing the connection error.

This is the Environment which we did build as brand new. We have one more existing environment, that got upgraded from old version of Dynamics.

In the Existing environment we used to connect the dataverse by using CrmServiceClient  with connection string like

var client = new CrmServiceClient(AuthType=Office365;Url=https://AAA.crm4.dynamics.com;UserName=AAA@ABC.onmicrosoft.com;Password=passcode;);

Our Existing environment connection is working fine as expected. But on the new environment it is throwing an error. When we try to the find out the root cause by troubleshooting, I came to know that the Use of the WS-Trust (Office365) authentication security protocol when connecting to Microsoft Dataverse is no longer recommended and has been deprecated.

It is working fine one existing environment as it got upgraded from old versions. And is throwing error on the new environment as it got build as brand new and is supporting all latest updates.

To fix this we have updated our connection process. There are multiple ways to connect, but we did use the Client ID and secret with ServiceClient.

var client = new ServiceClient(new Uri(envvar.CrmUrl), envvar.CrmTenantId, envvar.CrmSecret, false, null);

for this we used “Microsoft.PowerPlatform.Dataverse.Client“. package

Hope this help!

Environment Variables – Dynamics 365 – Power Apps

When I am trying to add components to my solution in Dynamics 365 Power Apps solution section under trail environment one thing which caught my attention is Environment Variables.

Environment Variable

By name it self I tried to understand that these are like Global Static variables which we can use at our environment level and can be used when we move our solutions to next higher environments.

I have explored little bit more on this. Here is the document for that.

Till now we are using the Custom entities to save the Configuration settings which can differ from one environment to higher environments. And we are using them in Plug-ins, workflows , Flows and Power Apps.

Now Environment variables allow us to transport application configuration data with solutions and optionally manipulate the values in our Application Lifecycle Management (ALM) pipeline. These Environment variables act as configurable input parameters allowing us to reference an environment variable within other solution components. We can update a value without modifying other components directly when using environment variables.

When should we use Environment variables:

  • When an input parameter needs to change across environments and should not be hard-coded. For example, a URL that points to a different resource in development and production environments.
  • If you’re building a solution where your customer is required to provide an input value.
  • Application setup pages.
  • When multiple components require the same input. Instead of entering that input multiple times, reference the environment variable. If the value needs to change, make an update in one place
  • If you need to update configuration values without modifying code or if the person managing the configuration is not familiar with coding. For example, a plugin that references a blob store location could be updating without directly modifying the plugin.

When we shouldn’t use Environment variables:

  • To transport secure data such as passwords or other secrets.
  • If several values are required for one definition.

Benefits of using environment variables:

  • No need to manually edit other solution components in a production environment.
  • Configure one or more variables in one place and reference like a parameter across multiple solution components.
  • Update configurable values without a code change.
  • Granular-level security managed by Common Data Service. etc..

Current limitations:

  • Caching. Plugins will need to run a query to fetch the values.
  • Canvas apps and flows can consume Environment variables just like entity record data. In the future we plan to build additional actions into canvas app and flow designers. This will simplify authoring and provide better visibility into environment variables being used by a specific app or flow. etc…

For the latest and detailed information about this feature, see the feature documentation at 

https://powerapps.microsoft.com/en-us/blog/environment-variables-available-in-preview/

https://docs.microsoft.com/en-us/power-platform-release-plan/2019wave2/microsoft-powerapps/new-solution-components-get-full-support

https://docs.microsoft.com/en-us/powerapps/maker/common-data-service/environmentvariables

In my coming blog, I will come-up with and example about how to create an environment variable in Power Apps and How they work.

Hope this helps 🙂

LIST OF DYNAMICS 365 ONLINE REGION IDENTIFIERS

Till now I got a change to work on the following regions where I was part of implementing the Dynamics 365 Customer Engagement solutions.

  1. North America
  2. EMEA
  3. APAC
  4. India
  5. United Kingdom

As we all know each region has different CRM region extension in URL. Now I got the question like what are the other pending regions where I can be part of the solutions implementation. So I started listing down all regions where I can be part in future. I found the list as below.

  • North America (NAM) (*.crm.dynamics.com)
  • South America (LATAM/SAM) (*.crm2.dynamics.com)
  • Canada (CAN) (*.crm3.dynamics.com)
  • Europe, Middle East, Africa (EMEA) (*.crm4.dynamics.com)
  • Asia Pacific (APAC) (*.crm5.dynamics.com)
  • Oceania (OCE) (Australia) (*.crm6.dynamics.com)
  • Japan (JPN) (*.crm7.dynamics.com)
  • India (IND) (*.crm8.dynamics.com)
  • North America 2-for Government (*.crm9.dynamics.com)
  • United Kingdom (UK) (*.crm11.dynamics.com)
  • France (FRA) (*.crm12.dynamics.com)
  • United Arab Emirates (UAE) (*.crm15.dynamics.com)
  • Microsoft Cloud Germany (DEU) (*.crm.microsoftdynamics.de)

I hope this list will be handy for them who are trying to understand the list of Dynamics 365 region identifiers.

Instance Type in Dynamics 365 And Administration Mode

The other day when I am working on creating new trial instance, I normally created an instance as we all do regularly. But after that I got the question like why can’t we explore more on these like what are the different types of instance we can create and what is the differences between them.

Then I started exploring more on this. Here is the little bit explanation I was able to document.

Instance Type: is the categorization of our Dynamics 365 instance (i.e. Production or Sandbox).

INSTANCE TYPE

There are multiple types of instances available in Dynamics 365

  1. Production
  2. Sandbox

Change a production environment to sandbox:

By default when we create our trial, we will get the Production Type Instance. And we can convert that to Sandbox instance by using option “Convert to Sandbox” in Power Platform admin center.

“Convert to sandbox” Option

Production: This is intended to be used for permanent work in an organization.

Sandbox: These are non-production environments, which offer features like copy and reset. Sandbox environments are used for development and testing, separate from production

Administration mode:
When we place a sandbox environment in administration mode, only users with System Administrator or System Customizer security roles will be able to sign in to that environment. Administration mode is useful when you want to make operational changes and not have regular users affect your work, and not have your work affect regular users.

Set administration mode

  1. Go to the Power Platform admin center and sign in using Environment Admin or System Administrator role credentials.
  2. From the left-side menu, select Environments, and then select a sandbox environment.
  3. Select See all.
  4. On the Details page, select Edit.
  5. Under Administration mode, toggle Disabled to Enabled.
  6. Set Background operations and Custom message, and then select Save.

Please find Microsoft documentation about this in this below link to explore more.

https://docs.microsoft.com/en-us/power-platform/admin/sandbox-environments#administration-mode

Hope this Helps:)

Automation of Activating or Deactivating Workflow / Business Rule on Dynamics 365 CE environment using PowerShell Script.

In One of my recent assignments, I came across this situation like we have one solution deployed to our production environment where I have couple of business rules and workflows on an entity.

Now as part of couple of requirements tweak, I have to remove the Business rule on the production environment. Instead of deleting I want to deactivate the Business rule so that in future if I require then I can reactivate it back.

To achieve this we can follow different approaches, but as I am getting expertise in implementing PowerShell script I have written a PowerShell script to execute on the required environment. Here is the script which helped us to activate / deactivate the Business rule.

Step 1: Created a CSV file where we can have all Workflows / Business Rules listed with ID and Name#

CSV file

Step 2: Created PowerShell Script to read this file and Process these Business Rules / Workflows

PowerShell Script

Note: Both Workflows and Business Rules are listed in workflow entity in Dynamics 365.

Hope this helps!