Skip to content

benjaminjohn.de Posts

How to delete a developer environment with Power Automate

Posted in Power Platform, Dynamics 365, and Power Automation

If you only understand the first and the last part of the title, you should click the button below to learn more about the “Power Apps Developer Plan” that includes a free Dataverse for developer (and for makers or course).

Normally Power Platform administrators can create, edit and delete Dataverse environments through the “Power Platform Admin Center” (https://admin.powerplatform.microsoft.com/environments), but developer environments from the “Power Apps Community Plan” differ here.

  • They can only be created through the “Power Apps Developer Plan” page at Microsoft (button above)
  • Everyone with Microsoft work or school account can create one personal development environment per tenant
  • They can not be edited (update name or URL) or deleted through the portal

How to delete a developer environment

I found out, that Nick Doelman already has perfectly described, how to delete a Power App Community Plan environment with PowerShell. Inspired by his blog post, I remembered that there is a “Power Platform for Admins” Connector for Power Automate (and Logic Apps) and I checked it out for you.

  • Open the the Maker Portal (https://make.powerapps.com) and select the default environment of your tenant on the right side of the header menu. Only there the Flow will be later reusable, because you don’t delete it with the environment it exists in.
  • Create a new instant Cloud Flow and give it a name, for example “Reset DevEnvironment”
  • Add an input parameter to the trigger action that will receive the environment ID
delete a developer environment
  • Search for the “Power Platform for Admins” connector and select it. I got the best search result by typing “PowerApp”.
the power platform for administrators connector
  • Now scroll down and select the “Delete Environment” action.
delete a developer environment with power automate
  • Select “Enter Custom Value” as environment input for the action and choose the ID that comes from the trigger action
delete a developer environment
  • Save your Flow

Usage of the flow

delete a developer environment

Now run the Flow and paste the Environment ID as parameter.

delete a developer environment

The flow run takes something between 30 and 120 seconds and ends with an 404 error, but at the end the environment has gone and you can create a new Power Apps Community Plan Environment again.

delete a developer environment

“Command Checker” bookmarklet

Posted in Dynamics 365, and Power Platform

Last week, I found out that Microsoft released a Command Checker for model-driven-app-ribbons – OVER 2 YEARS AGO! I totally missed that.
I especially love that it shows me the result of each single display rule and enable rule.

To enable the Command Checker as a button in the ribbon bar, you need to add the URL parameter “ribbondebug=true” to the current D365 CE URL and reload it. But who wants to remember ugly URL parameters…

javascript: (var _href = window.location.href; if (_href.includes("ribbondebug")){_href.replace("ribbondebug=false", "ribbondebug=true")} else {_href += "&ribbondebug=true"} window.location.href = _href)

Open these bookmarklet anywhere in model-driven-app, and it will reload the window with the activated Command Checker.

“Advanced Find” bookmarklet

Posted in Dynamics 365, and Power Platform

Since February 2022, Power Platform Admins can enable the “Modern advanced find in model driven apps“. After a decade of continuity, it is great to see a fresh, clean look and some new features in a unified user interface.

In case you are a CRM veteran like me and also miss the old advanced search, I have something for you.

javascript: (window.open(Xrm.Utility.getGlobalContext().getCurrentAppUrl() + "&pagetype=advancedfind"))

Open these bookmarklet anywhere in Dataverse, and it will open a new window with the classic advanced find in it.
Don’t forget to get used to the new advanced find.

“Get attribute by attribute ID” bookmarklet

Posted in Dynamics 365

Background information

Currently, I have a problem while applying a solution upgrade for our managed solution. The message in the solution history gives me the name of the attribute that blocks the uninstallation and its ID, but it did not tell me to which entity the attribute belongs.

Get attribute by attribute ID

To identify the right entity for the attribute professionally and not by trail and error, I looked into the “Query table definitions using the Web API” article on Microsoft Docs and build a browser bookmarklet for an easier use.

The “Get attribute by attribute ID” bookmarket

Copy and paste the following code as URL of a bookmark in your browser and execute it on any D365 page.

javascript:function getDet(){var r=JSON.parse(this.responseText);console.info("MetaData for Entity: " + r.LogicalName);console.dir(r);console.info("MetaData for Attribute: " + r.Attributes[0].LogicalName);console.dir(r.Attributes[0])};function getAtt(){var r=JSON.parse(this.responseText).value,etn,atn;for (let i=0; i < r.length; i++) {if (r[i].Attributes.length > 0) {Xrm.Navigation.openAlertDialog({confirmButtonLabel:"Close",text:"Entity: "+r[i].LogicalName+"\nAttribute: "+r[i].Attributes[0].LogicalName+"\n-\nOpen Browser Console for more MetaData Details (F12)",title:"Found Attribute"},{height:250,width:350});var oReq=new XMLHttpRequest();oReq.addEventListener("load", getDet);oReq.open("GET","/api/data/v9.0/EntityDefinitions(LogicalName='"+r[i].LogicalName+"')?$expand=Attributes($filter=MetadataId%20eq%20"+id+")");oReq.send();break;}}}id=prompt("Enter Attribute ID", "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX");var oReq=new XMLHttpRequest();oReq.addEventListener("load", getAtt);oReq.open("GET","api/data/v9.0/EntityDefinitions()?$select=LogicalName&$expand=Attributes($select=LogicalName;$filter=MetadataId%20eq%20"+id+")");oReq.send();

You can paste the attribute ID and receive the logical name of the attribute and of its entity. On top, you can open the browser console to inspect the full output of the WebApi for the attribute.

Bulk active Flows from a solution

Posted in Power Automation, Dynamics 365, and Power Platform

Scenario

We start our projects with our best practice solution and add further value over time to that solution. We also try to let benefit existing customers from the innovations and optimizations that get implemented in the solution over time, since their project has started.
Knowing our goal, you can imagine our setup. A source instance in our tenant and several target instances at different customers.
On top, some customers receive manual, an unmanaged version of the solution and other customers receive a managed version with an Azure Pipeline.

Issue

Flows can only be turned on if the user turning them on has permissions to connections being referenced by the connection reference.

Marc Schweigert: https://gist.github.com/devkeydet/f31554566b2e53ddd8e7e1db4af555a6

This causes no issues when importing manually, but as we use Application User to connect the Azure Pipeline, this ends with all Flows in the solution turned off after solution import.

Solution – Bulk active Flows

One solution would be to create a PowerShell script in the Azure Pipeline that impersonate the owner of a connection reference (Source).
I decided to create a Power Automated based solution to bulk active Flows, with an Environment Variable that contains Flows that should not be enabled automatically.

Step by step

Step 1 – Environment Variable:
Create an Environment Variable of type JSON to store the Flows that should not be activated automatically. Doing this as an Environment Variable enables you to define this per instance.

To enable our Flow to find the right Flows by name, workflowid or workflowuniqueid, the structure should be:

{
  "Flow 1": "worklowid",
  "Flow 2": "workflowidunique"
}

Step 2: The Trigger of the Flow

A managed solution only get modified when you import an update of it. Therefore, this is my trigger, filtered on my solution.

The dataverse flow trigger on table 'Solutions'.

Step 3: Some vars and const

Vars and const for the Flow.

Step 4: Get the exclusion list

I needed to put it in a compose action. Working directly with the environment variable did not work for me.

Load the exclusion list in a compose.

Step 5: Get inactive Flows from the solution

Get the inactive Flows from the solution with a fetch to bulk active flows later.

I found the FetchXml in the Dynamics Community, it was an answer from Scott Durow where he helped someone. By that way, thank you, Scott, that inspired me to my solution.

<fetch>
  <entity name="workflow">
    <attribute name="category" />
    <attribute name="name" />
    <attribute name="statecode" />
    <attribute name="workflowidunique" />
    <filter>
      <condition attribute="category" operator="eq" value="5" />
      <condition attribute="statecode" operator="eq" value="0" />
    </filter>
    <link-entity name="solutioncomponent" from="objectid" to="workflowid">
      <link-entity name="solution" from="solutionid" to="solutionid">
        <filter>
          <condition attribute="uniquename" operator="eq" value=@{outputs('Solution')} />
        </filter>
      </link-entity>
    </link-entity>
  </entity>
</fetch>

Step 6: Loop over fetched Flows

Loop to bulk active Flows.

Step 6.1 Check inside the loop if the current Flow is not excluded

Condition to excluded flows from the environment variable.
contains(string(outputs('Get_ExclusionList')), string(items('Loop_fetched_Processes_from_Solution')?['workflowid']))


contains(string(outputs('Get_ExclusionList')), string(items('Loop_fetched_Processes_from_Solution')?['workflowidunique']))


contains(string(outputs('Get_ExclusionList')), string(items('Loop_fetched_Processes_from_Solution')?['name']))

Step 6.1.1 Activate the current Flow in the TRUE path of the condition

Update the record in Dataverse to activate the flow.

Step 6.1.2 Log if an error happens after activating the current Flow

A counter and string for error logging.

Click the three dots on the “Counter++” action and choose “Configure run after”.

Open the 'run after' menu.
Configure the 'run after' option.

Step 7: Check if an error occurred, after the loop is completed

Condition to inform about errors.

Step 7.1 If an error occurred, get the URL of the CRM instance

Get the CRM URL from OData.Id.

I described how to get it in my post: Get CRM URL in Power Automate

Step 7.2 Send a notification

Send an email with Power Automate.

Let me a comment if you find this helpful or how you solved this or a similar problem.