Saturday, January 12, 2019

Dynamics 365 - Copying Notes from a Lead to an Account

We had a requirement to copy notes from a lead onto an account, when the lead is qualified. There is no OOB way to do this, but I found a Workflow library called “msdyncrmWorkflowTools” that has a step that can do this. Here is how:

The step is called “Clone Children”:

First install the Workflow library by downloading the solution from and importing the solution into your CRM solution.

  1. Next create a workflow process that is attached to the “Account” entity.

  2. After you save it, open the newly created process.
  3. Set the scope to “Organization” (not a required step)
  4. Set the execute as to “owner of the process” (not a required step)
  5. And set the process to run when the “record is created”
  6. Next add a check condition to see if the account’s Originating Lead has been set, which would signal that the account was being created from a lead.
  7. Next add the Clone Children step from “msdyncrmWorkflowTools (
  8. Set the properties to the following values:
    image image
    The relationship name is case-sensitive, so enter it as Lead_Annotation.
    The new parent field, which is used for the old parent field name is objectid.
  9. Save and activate the process and test it!

Friday, January 04, 2019

XrmToolbox–useful build settings

  1. ILMerge
    Used, when you have multiple assemblies and you need to package them together.
    Stage: Post Build Step

  2. ilmerge.exe /target:library /targetplatform:v4,"C:\Windows\Microsoft.NET\Framework\v4.0.30319" "/out:CombinedModuleName.dll" "inputModule1.dll" "inputModule2.dll" "inputModule3.dll"

  3. Copy the plugin to a plugins folder
    This makes it easier to tell XTB to load the dll you are developing

  4. if $(ConfigurationName) == Debug (
      IF NOT EXIST Plugins mkdir Plugins
      move /Y  "CombinedModuleName.dll" Plugins
  5. Debug settings:
    Start external program: path to xrmtoolbox.exe
    Command line arguments:
    /plugin:"NameOfThePlugin" /overridepath:"path to the parent of plugin folder" /connection:"specific connection if you want to use one"

    Note: in step 2, we create a folder called Plugins under the debug output folder (eg: {ProjectName}\bin\Debug\Plugins). The path that OverRidePath should point to is the Debug folder. The reason is that XTB will look for a sub-folder called plugins to locate the plugin.

For more information:

Wednesday, January 02, 2019

Xrm.Page is deprecated–what to do in v9+

According to this:, in V9, Xrm.Page is being deprecated. Xrm.Page used to be used in Javascript called by forms as well as the ribbon.

The fix is documented here:



The gist:


  1. Pass the executionContext from the handler: see
  2. Add a parameter on your js function to accept the executionContext
  3. call getFormContext() on your parameter to get the form-context. See:

function functionCalledDirectlyByTheForm(executionContext)
     var formContext = executionContext.getFormContext(); // get formContext

    // use formContext instead of Xrm.Page 
     var firstName = formContext.getAttribute("firstname").getValue();
     var lastName = formContext.getAttribute("lastname").getValue();
     console.log(firstName + " " + lastName);


  1. Pass the PrimaryControl as a CRM Parameter to your javascript function
    In Ribbon Workbench:
  2. Add a parameter on your js function to accept the primaryControl as a parameter
    function OnMyRibbonButtonAction(commandProperties, primaryControl) {
  3. use the PrimaryControl parameter as though it were the formContext:

function functionCalledDirectlyByTheRibbon(primaryControl)
    // use primaryControl instead of Xrm.Page 
    var firstName = primaryControl.getAttribute("firstname").getValue();
     var lastName = primaryControl.getAttribute("lastname").getValue();
     console.log(firstName + " " + lastName);


Dont use getFormContext in a function called by the ribbon. “getFormContext” is not available in the UCI, and so even though it may work in the legacy web-client, it will break when you begin using the UCI.

If you want a function to work when called from the form as well as the ribbon and you want it to work with the web-client and UCI, do something like this:

//use this to get an object which you can use like the formContext.
//this code can be called from a function that was either invoked from a form or from the ribbon.
function getFormContext(executionContext) {
     var formContext = null;
     if (executionContext !== null) {
         if (typeof executionContext.getAttribute === 'function') {
             formContext = executionContext; //most likely called from the ribbon.
         } else if (typeof executionContext.getFormContext === 'function'
                 && typeof(executionContext.getFormContext()).getAttribute === 'function') {
             formContext = executionContext.getFormContext(); // most likely called from the form via a handler
         } else {
             throw 'formContext was not found'; //you could do formContext = Xrm.Page; if you like.
     return formContext;


Because Xrm.Page is deprecated, you can no longer use Xrm.Page.context. Instead, you should use Xrm.Utility.getGlobalContext(). This method returns an object that supports most of the methods that were available from Xrm.Page.context.


This formContext diagram is extremely useful for determining what is available from the formContext and what is not:

formContext object model


Understand the Client API object model: