<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[utilities - Alexander Development]]></title><description><![CDATA[utilities - Alexander Development]]></description><link>https://alexanderdevelopment.net/</link><image><url>https://alexanderdevelopment.net/favicon.png</url><title>utilities - Alexander Development</title><link>https://alexanderdevelopment.net/</link></image><generator>Ghost 1.20</generator><lastBuildDate>Fri, 24 Apr 2026 14:15:57 GMT</lastBuildDate><atom:link href="https://alexanderdevelopment.net/tag/utilities/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Updated solution for scheduling recurring Dynamics 365 workflows]]></title><description><![CDATA[<div class="kg-card-markdown"><p>I've released an updated version of my recurring workflow scheduler for Dynamics 365 Customer Engagement. This solution targets Dynamics 365 version 9, so it should work in all current Dynamics 365 online organizations. You can download version 1.3 of my solution from here: <a href="https://github.com/lucasalexander/AlexanderDevelopment.ProcessRunner/releases/tag/v1.3">https://github.com/lucasalexander/AlexanderDevelopment.ProcessRunner/</a></p></div>]]></description><link>https://alexanderdevelopment.net/post/2018/03/12/updated-solution-for-scheduling-recurring-dynamics-crm-workflows-2/</link><guid isPermaLink="false">5aa6908f44999a000186ddb1</guid><category><![CDATA[Microsoft Dynamics CRM]]></category><category><![CDATA[Dynamics 365]]></category><category><![CDATA[utilities]]></category><category><![CDATA[FetchXML]]></category><category><![CDATA[process automation]]></category><dc:creator><![CDATA[Lucas Alexander]]></dc:creator><pubDate>Mon, 12 Mar 2018 15:00:00 GMT</pubDate><media:content url="https://alexanderdevelopment.net/content/images/2018/03/chrome_2018-03-12_09-40-49.png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://alexanderdevelopment.net/content/images/2018/03/chrome_2018-03-12_09-40-49.png" alt="Updated solution for scheduling recurring Dynamics 365 workflows"><p>I've released an updated version of my recurring workflow scheduler for Dynamics 365 Customer Engagement. This solution targets Dynamics 365 version 9, so it should work in all current Dynamics 365 online organizations. You can download version 1.3 of my solution from here: <a href="https://github.com/lucasalexander/AlexanderDevelopment.ProcessRunner/releases/tag/v1.3">https://github.com/lucasalexander/AlexanderDevelopment.ProcessRunner/releases/tag/v1.3</a>.</p>
<p>For more information on the use of this tool, take a look at the original blog posts:</p>
<ul>
<li><a href="https://alexanderdevelopment.net/post/2016/09/19/updated-solution-for-scheduling-recurring-dynamics-crm-workflows/">https://alexanderdevelopment.net/post/2016/09/19/updated-solution-for-scheduling-recurring-dynamics-crm-workflows/</a></li>
<li><a href="https://alexanderdevelopment.net/post/2013/05/18/scheduling-recurring-dynamics-crm-workflows-with-fetchxml/">https://alexanderdevelopment.net/post/2013/05/18/scheduling-recurring-dynamics-crm-workflows-with-fetchxml/</a></li>
</ul>
</div>]]></content:encoded></item><item><title><![CDATA[Dynamics 365 Configuration Data Mover v2.4]]></title><description><![CDATA[<div class="kg-card-markdown"><p>I've released an <a href="https://github.com/lucasalexander/AlexanderDevelopment.ConfigDataMover/releases/tag/v2.4.6587.18905">updated version</a> of my popular Dynamics 365 Configuration Data Mover utility that was built with .Net 4.7 to address the new requirement to use TLS 1.2 (or better) for connections to Dynamics 365 online instances as described in this entry on the Microsoft Dynamics 365</p></div>]]></description><link>https://alexanderdevelopment.net/post/2018/01/16/dynamics-365-configuration-data-mover-v2-4/</link><guid isPermaLink="false">5a5e85dae2df920001a88f85</guid><category><![CDATA[Microsoft Dynamics CRM]]></category><category><![CDATA[Dynamics 365]]></category><category><![CDATA[Configuration Data Mover]]></category><category><![CDATA[integration]]></category><category><![CDATA[utilities]]></category><dc:creator><![CDATA[Lucas Alexander]]></dc:creator><pubDate>Tue, 16 Jan 2018 23:12:00 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p>I've released an <a href="https://github.com/lucasalexander/AlexanderDevelopment.ConfigDataMover/releases/tag/v2.4.6587.18905">updated version</a> of my popular Dynamics 365 Configuration Data Mover utility that was built with .Net 4.7 to address the new requirement to use TLS 1.2 (or better) for connections to Dynamics 365 online instances as described in this entry on the Microsoft Dynamics 365 team blog: <a href="https://blogs.msdn.microsoft.com/crm/2017/09/28/updates-coming-to-dynamics-365-customer-engagement-connection-security">https://blogs.msdn.microsoft.com/crm/2017/09/28/updates-coming-to-dynamics-365-customer-engagement-connection-security</a>.</p>
<p>This upgrade is fully compatible with existing job files.</p>
<h4 id="gettingthedynamics365configurationdatamover">Getting the Dynamics 365 Configuration Data Mover</h4>
<p>The source code is available in my GitHub repository <a href="https://github.com/lucasalexander/AlexanderDevelopment.ConfigDataMover">here</a>.</p>
<p>A compiled version can be downloaded <a href="https://github.com/lucasalexander/AlexanderDevelopment.ConfigDataMover/releases/tag/v2.4.6587.18905">here</a>.</p>
</div>]]></content:encoded></item><item><title><![CDATA[Using proxy connections with the Dynamics 365 Configuration Data Mover]]></title><description><![CDATA[<div class="kg-card-markdown"><p>I was recently asked to add a feature to my Dynamics 365 Configuration Data Mover to enable connections through a proxy server. Because the tool is a .Net application, proxy server connections can be configured directly in the AlexanderDevelopmentConfigDataMover.exe.config file. For example, if you want to use the</p></div>]]></description><link>https://alexanderdevelopment.net/post/2018/01/08/using-proxy-connections-with-the-dynamics-365-configuration-data-mover/</link><guid isPermaLink="false">5a5837246636a30001b978f1</guid><category><![CDATA[Microsoft Dynamics CRM]]></category><category><![CDATA[Dynamics 365]]></category><category><![CDATA[Configuration Data Mover]]></category><category><![CDATA[integration]]></category><category><![CDATA[utilities]]></category><dc:creator><![CDATA[Lucas Alexander]]></dc:creator><pubDate>Mon, 08 Jan 2018 15:16:49 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p>I was recently asked to add a feature to my Dynamics 365 Configuration Data Mover to enable connections through a proxy server. Because the tool is a .Net application, proxy server connections can be configured directly in the AlexanderDevelopmentConfigDataMover.exe.config file. For example, if you want to use the default Internet Explorer proxy settings, just add the following values inside the <configuration> element:</configuration></p>
<pre><code>&lt;system.net&gt;
  &lt;defaultproxy enabled=&quot;true&quot;&gt; 
    &lt;proxy usesystemdefault=&quot;true&quot;/&gt; 
  &lt;/defaultproxy&gt; 
&lt;/system.net&gt;
</code></pre>
<p>For more information on proxy settings, take a look at this Microsoft overview on .Net <a href="https://docs.microsoft.com/en-us/dotnet/framework/network-programming/proxy-configuration">proxy configuration</a>.</p>
</div>]]></content:encoded></item><item><title><![CDATA[A Dynamics 365 local message listener for web client notifications - part 3]]></title><description><![CDATA[<div class="kg-card-markdown"><p>Several months ago I discussed an <a href="https://alexanderdevelopment.net/post/2017/07/19/a-dynamics-365-local-message-listener-for-web-client-notifications-part-1/">approach</a> for passing notifications from local applications to the Dynamics 365 web client through a message listener process that runs on an end user's PC and shared some <a href="https://alexanderdevelopment.net/post/2017/07/21/a-dynamics-365-local-message-listener-for-web-client-notifications-part-2/">sample code</a> for how to implement it.</p>
<p>Recently I used this approach to establish communication between</p></div>]]></description><link>https://alexanderdevelopment.net/post/2017/12/28/a-dynamics-365-local-message-listener-for-web-client-notifications-part-3/</link><guid isPermaLink="false">5a5837246636a30001b978ec</guid><category><![CDATA[Microsoft Dynamics CRM]]></category><category><![CDATA[Dynamics 365]]></category><category><![CDATA[integration]]></category><category><![CDATA[utilities]]></category><dc:creator><![CDATA[Lucas Alexander]]></dc:creator><pubDate>Thu, 28 Dec 2017 17:53:33 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p>Several months ago I discussed an <a href="https://alexanderdevelopment.net/post/2017/07/19/a-dynamics-365-local-message-listener-for-web-client-notifications-part-1/">approach</a> for passing notifications from local applications to the Dynamics 365 web client through a message listener process that runs on an end user's PC and shared some <a href="https://alexanderdevelopment.net/post/2017/07/21/a-dynamics-365-local-message-listener-for-web-client-notifications-part-2/">sample code</a> for how to implement it.</p>
<p>Recently I used this approach to establish communication between Dynamics 365 web resources and a fingerprint reader attached to a local PC. The actual coding was fairly simple, but I did run into a problem that I did not encounter when I built my original proof-of-concept message listener because I was accessing Dynamics 365 via HTTPS as opposed to HTTP like I had been in my on-prem development sandbox. Because mixed content can be a security risk, modern browsers typically block pages that are accessed via HTTPS from loading scripts over HTTP, which is how my listener process was running.</p>
<p>In order to make my listener process accessible via HTTPS, I did the following:</p>
<ol>
<li>Generated a self-signed SSL certificate to represent a root certificate authority.</li>
<li>Generated an SSL certificate signed by my root CA to encrypt communication with my message listener process.</li>
<li>Added the root SSL certificate from step #1 as a trusted root certificate on the local PC.</li>
<li>Added the SSL certificate from step #2 to the personal certificate store on the local PC.</li>
<li>Bound the SSL certificate from step #2 to the port my listener process uses.</li>
</ol>
<h4 id="generatingthecertificates">Generating the certificates</h4>
<p>This <a href="http://blog.davidchristiansen.com/2016/09/howto-create-self-signed-certificates-with-powershell/">blog post</a> has detailed steps I followed to generate self-signed certificates with PowerShell's <a href="https://docs.microsoft.com/en-us/powershell/module/pkiclient/new-selfsignedcertificate?view=win10-ps">New-SelfSignedCertificate</a> cmdlet. In the past I have used OpenSSL to generate self-signed certificates, and while OpenSSL would definitely work here, I found the PowerShell approach to be much  easier for my initial development purposes.</p>
<p><em>(A note on security - As I look at making this solution fully ready for production, I need to do some further investigation into the security implications of using self-signed certificates. Because I am only using them to enable communication with a process running on the local PC, I think the risks are minimal as long as the root certificate is kept secure.)</em></p>
<h4 id="installingthecertificates">Installing the certificates</h4>
<p>Once you have generated your two SSL certificates, you need to install them on the local PC. If you followed the directions from the blog post above to generate your certificates, you should have a public certificate for your root CA as a .cer file and a private certificate to use for the application as a .pfx file.</p>
<p>To install the root certificate as a trusted root certificate authority, do the following:</p>
<ol>
<li>Double-click public certificate (.cer file) for the root CA you generated. The certificate properties window will open. Click &quot;install certificate.&quot; <img src="https://alexanderdevelopment.net/content/images/2017/12/import-cer-01.png#img-thumbnail" alt="Install root CA - step 1"></li>
<li>The certificate import wizard will open. Select &quot;local machine&quot; and click next. <img src="https://alexanderdevelopment.net/content/images/2017/12/import-cer-02.png" alt="Install root CA - step 2"></li>
<li>You may be presented with a confirmation dialog asking if you &quot;want to allow this app to make changes to your device.&quot; If so, click yes.</li>
<li>On the next screen, select &quot;place all certificates in the following store&quot; and click browse.</li>
<li>Select &quot;trusted root certification authorities.&quot;<img src="https://alexanderdevelopment.net/content/images/2017/12/import-cer-03.png#img-thumbnail" alt="Install root CA - step 5"></li>
<li>Verify the certificate store input shows &quot;trusted root certification authorities&quot; and click next.<img src="https://alexanderdevelopment.net/content/images/2017/12/import-cer-04.png#img-thumbnail" alt="Install root CA - step 6"></li>
<li>Click finish.<img src="https://alexanderdevelopment.net/content/images/2017/12/import-cer-05.png#img-thumbnail" alt="Install root CA - step 7"></li>
<li>You will receive a success message. Click OK to close it.</li>
<li>Close the certificate properties window.</li>
</ol>
<p>To install the SSL certificate that will encrypt communication with the message listener, do the following:</p>
<ol>
<li>Double-click private certificate (.pfx) for the application certificate CA you generated. The certificate import wizard will open. Select &quot;local machine&quot; and click next.<img src="https://alexanderdevelopment.net/content/images/2017/12/import-pfx-01.png#img-thumbnail" alt="Install application certificate - step 1"></li>
<li>You may be presented with a confirmation dialog asking if you &quot;want to allow this app to make changes to your device.&quot; If so, click yes.</li>
<li>You will see the name of your .pfx file in the file name input box. Click next. <img src="https://alexanderdevelopment.net/content/images/2017/12/import-pfx-02.png#img-thumbnail" alt="Install application certificate - step 3"></li>
<li>Enter the password for the .pfx file and click next.<img src="https://alexanderdevelopment.net/content/images/2017/12/import-pfx-03.png#img-thumbnail" alt="Install application certificate - step 4"></li>
<li>On the next screen, select &quot;place all certificates in the following store&quot; and click browse.</li>
<li>Select &quot;personal.&quot;<img src="https://alexanderdevelopment.net/content/images/2017/12/import-pfx-04.png#img-thumbnail" alt="Install application certificate - step 6"></li>
<li>Verify the certificate store input shows &quot;personal&quot; and click next.<img src="https://alexanderdevelopment.net/content/images/2017/12/import-pfx-05.png#img-thumbnail" alt="Install application certificate - step 7"></li>
<li>Click finish.<img src="https://alexanderdevelopment.net/content/images/2017/12/import-pfx-06.png#img-thumbnail" alt="Install application certificate - step 8"></li>
</ol>
<h4 id="bindingtheapplicationsslcertificatetothemessagelistenerport">Binding the application SSL certificate to the message listener port</h4>
<p>Once you have installed the certificates on the local PC, you can bind the application SSL certificate to the port on which the message listener is listening. I am using Windows 10, but the directions outlined in this <a href="https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-configure-a-port-with-an-ssl-certificate">Microsoft document</a> for Windows Vista worked for me. Presumably they will also work for Windows 7 and 8.</p>
<p>If you don't feel like reading the entire document, basically you can use the <a href="https://technet.microsoft.com/en-us/library/bb490939.aspx?f=255&amp;MSPPError=-2147217396">netsh</a> command to encrypt all requests on a specific port for a specific application using a specific SSL certificate. Here's how to configure it:</p>
<ol>
<li>Get the thumbprint from the SSL certificate you installed in the &quot;personal&quot; store following the instructions here - <a href="https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-retrieve-the-thumbprint-of-a-certificate">https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-retrieve-the-thumbprint-of-a-certificate</a>.</li>
<li>Get the application id from your message listener application. If your message listener is a .Net application, you would use the &quot;Assembly: Guid&quot; value from your application's AssemblyInfo file.</li>
<li>Open a command prompt as an administrator and execute the following command: <code>netsh http add sslcert ipport=0.0.0.0:9345 certhash=CC5F7BF58FD666EEC844C1B949E9661267A8A310 appid={b31bee72-c2ac-411e-959b-adbd25bba2cf}</code> You will need to substitute your specific values for &quot;ipport,&quot; &quot;certhash&quot; and &quot;appid.&quot;</li>
<li>Verify your configuration works by starting your message listener and then making an HTTPS request.</li>
</ol>
<p>Assuming everything works, you should now be able to access your local message listener process from your Dynamics 365 web resources. If you want to use the message listener on other PCs, you don't have to regenerate new certificates. You can just install the same certificates and run the same netsh command on every PC where the listener application will run.</p>
<p>What do think about this approach? Are there any real-world scenarios where it would be useful for you?</p>
</div>]]></content:encoded></item><item><title><![CDATA[Creating many-to-many associations with the Dynamics 365 Configuration Data Mover]]></title><description><![CDATA[<div class="kg-card-markdown"><p>I've released an updated version of my popular Dynamics 365 Configuration Data Mover utility that includes the ability to create many-to-many associations in the target system. This upgrade is fully compatible with existing job files.</p>
<p>To create a many-to-many job step in the GUI, select the new &quot;many to</p></div>]]></description><link>https://alexanderdevelopment.net/post/2017/11/28/creating-many-to-many-associations-with-the-dynamics-365-configuration-data-mover/</link><guid isPermaLink="false">5a5837246636a30001b978e6</guid><category><![CDATA[Microsoft Dynamics CRM]]></category><category><![CDATA[Dynamics 365]]></category><category><![CDATA[Configuration Data Mover]]></category><category><![CDATA[integration]]></category><category><![CDATA[utilities]]></category><dc:creator><![CDATA[Lucas Alexander]]></dc:creator><pubDate>Tue, 28 Nov 2017 20:00:00 GMT</pubDate><media:content url="https://alexanderdevelopment.net/content/images/2017/11/AlexanderDevelopment-ConfigDataMover_2017-11-28_10-28-59.png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://alexanderdevelopment.net/content/images/2017/11/AlexanderDevelopment-ConfigDataMover_2017-11-28_10-28-59.png" alt="Creating many-to-many associations with the Dynamics 365 Configuration Data Mover"><p>I've released an updated version of my popular Dynamics 365 Configuration Data Mover utility that includes the ability to create many-to-many associations in the target system. This upgrade is fully compatible with existing job files.</p>
<p>To create a many-to-many job step in the GUI, select the new &quot;many to many&quot; step type and input a FetchXML query for the relationship entity (relationship entity name on the many-to-many relationship form) that includes the GUID fields for each entity. The relationship entities cannot be queried in the advanced find builder, so you must write the FetchXML manually or use a separate query builder.</p>
<p><img src="https://alexanderdevelopment.net/content/images/2017/11/AlexanderDevelopment-ConfigDataMover_2017-11-28_10-28-59-1.png#img-thumbnail" alt="Creating many-to-many associations with the Dynamics 365 Configuration Data Mover"></p>
<p>One thing to keep in mind is that a many-to-many job step will create many-to-many record associations in the target system, but it will not delete any existing N:N associations that have been removed in the source.</p>
<h4 id="gettingthedynamics365configurationdatamover">Getting the Dynamics 365 Configuration Data Mover</h4>
<p>The source code is available in my GitHub repository <a href="https://github.com/lucasalexander/AlexanderDevelopment.ConfigDataMover">here</a>.</p>
<p>A compiled version can be downloaded <a href="https://github.com/lucasalexander/AlexanderDevelopment.ConfigDataMover/releases">here</a>.</p>
</div>]]></content:encoded></item><item><title><![CDATA[Dynamics 365 Configuration Data Mover v2.2]]></title><description><![CDATA[<div class="kg-card-markdown"><p>I've released an updated version of my popular Dynamics 365 Configuration Data Mover utility that includes the following features:</p>
<ul>
<li>Path to source and target JSON data files can now be absolute or relative to current working directory. This is particularly useful for running the CLI tool in an automated fashion.</li></ul></div>]]></description><link>https://alexanderdevelopment.net/post/2017/09/11/dynamics-365-configuration-data-mover-v2-2/</link><guid isPermaLink="false">5a5837246636a30001b978db</guid><category><![CDATA[Microsoft Dynamics CRM]]></category><category><![CDATA[Dynamics 365]]></category><category><![CDATA[Configuration Data Mover]]></category><category><![CDATA[integration]]></category><category><![CDATA[utilities]]></category><dc:creator><![CDATA[Lucas Alexander]]></dc:creator><pubDate>Mon, 11 Sep 2017 17:17:17 GMT</pubDate><media:content url="https://alexanderdevelopment.net/content/images/2017/09/cmd_2017-09-11_12-15-24.png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://alexanderdevelopment.net/content/images/2017/09/cmd_2017-09-11_12-15-24.png" alt="Dynamics 365 Configuration Data Mover v2.2"><p>I've released an updated version of my popular Dynamics 365 Configuration Data Mover utility that includes the following features:</p>
<ul>
<li>Path to source and target JSON data files can now be absolute or relative to current working directory. This is particularly useful for running the CLI tool in an automated fashion.</li>
<li>Location of job configuration file can be passed to CLI tool as absolution or relative path.</li>
<li>Import tool can now read configuration data directly as a JSON string instead of having to read it from a file. The syntax for supplying the the data to the CLI tool (or importer library DLL) is <em>RAWJSON={YOUR_EXPORT_JSON_HERE}</em></li>
</ul>
<p>This upgrade is fully compatible with existing job files.</p>
<h4 id="gettingthedynamics365configurationdatamover">Getting the Dynamics 365 Configuration Data Mover</h4>
<p>The source code is available in my GitHub repository <a href="https://github.com/lucasalexander/AlexanderDevelopment.ConfigDataMover">here</a>.</p>
<p>A compiled version can be downloaded <a href="https://github.com/lucasalexander/AlexanderDevelopment.ConfigDataMover/releases">here</a>.</p>
</div>]]></content:encoded></item><item><title><![CDATA[Running Dynamics 365 Configuration Data Mover jobs in Azure Functions]]></title><description><![CDATA[<div class="kg-card-markdown"><p>My <a href="https://alexanderdevelopment.net/tag/configuration-data-mover/">Dynamics 365 Configuration Data Mover</a> utility allows you to run synchronization jobs from an interactive GUI tool or the command line, but the actual data synchronization logic is contained in a separate AlexanderDevelopment.ConfigDataMover.Lib.dll file that can be included in other applications. In today's post I will</p></div>]]></description><link>https://alexanderdevelopment.net/post/2017/08/09/running-dynamics-365-configuration-data-mover-jobs-in-azure-functions/</link><guid isPermaLink="false">5a5837246636a30001b978d4</guid><category><![CDATA[Microsoft Dynamics CRM]]></category><category><![CDATA[Dynamics 365]]></category><category><![CDATA[integration]]></category><category><![CDATA[utilities]]></category><category><![CDATA[Configuration Data Mover]]></category><category><![CDATA[Azure]]></category><dc:creator><![CDATA[Lucas Alexander]]></dc:creator><pubDate>Wed, 09 Aug 2017 19:13:58 GMT</pubDate><media:content url="https://alexanderdevelopment.net/content/images/2017/08/chrome_2017-08-09_12-44-48-1.png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://alexanderdevelopment.net/content/images/2017/08/chrome_2017-08-09_12-44-48-1.png" alt="Running Dynamics 365 Configuration Data Mover jobs in Azure Functions"><p>My <a href="https://alexanderdevelopment.net/tag/configuration-data-mover/">Dynamics 365 Configuration Data Mover</a> utility allows you to run synchronization jobs from an interactive GUI tool or the command line, but the actual data synchronization logic is contained in a separate AlexanderDevelopment.ConfigDataMover.Lib.dll file that can be included in other applications. In today's post I will show how you can set up an Azure Function to execute a Configuration Data Mover job file to sync data between two Dynamics 365 organizations.</p>
<h4 id="settingupyourazurefunction">Setting up your Azure Function</h4>
<p>First create a new Azure Function. I created an HTTP trigger function with the default &quot;function&quot; authorization level so that I could post parameters to it, but if you could modify the code sample later in this post to use it with a different type of trigger. <img src="https://alexanderdevelopment.net/content/images/2017/08/chrome_2017-08-09_12-37-17.png#img-thumbnail" alt="Running Dynamics 365 Configuration Data Mover jobs in Azure Functions"></p>
<p>Next open your function's <a href="https://blogs.msdn.microsoft.com/benjaminperkins/2017/04/13/how-to-add-assembly-references-to-an-azure-function-app/">Kudu console</a> so you can create a &quot;bin&quot; directory to upload the AlexanderDevelopment.ConfigDataMover.Lib.dll file. <img src="https://alexanderdevelopment.net/content/images/2017/08/chrome_2017-08-09_12-38-26.png#img-thumbnail" alt="Running Dynamics 365 Configuration Data Mover jobs in Azure Functions"></p>
<p>Navigate to the correct directory and create a &quot;bin&quot; directory inside it. <img src="https://alexanderdevelopment.net/content/images/2017/08/chrome_2017-08-09_12-38-56.png#img-thumbnail" alt="Running Dynamics 365 Configuration Data Mover jobs in Azure Functions"></p>
<p>After that, go back to the main function editor interface to see the newly created &quot;bin&quot; directory in the &quot;view files&quot; area. <img src="https://alexanderdevelopment.net/content/images/2017/08/chrome_2017-08-09_12-39-17.png" alt="Running Dynamics 365 Configuration Data Mover jobs in Azure Functions"></p>
<p>Look in the local directory where you have installed the Configuration Data Mover and find the &quot;AlexanderDevelopment.ConfigDataMover.Lib.dll&quot; file. Upload it to the &quot;bin&quot; directory you just created. <img src="https://alexanderdevelopment.net/content/images/2017/08/chrome_2017-08-09_12-39-35.png#img-thumbnail" alt="Running Dynamics 365 Configuration Data Mover jobs in Azure Functions"></p>
<p>Navigate back to the main function directory and create a project.json file to pull in dependencies via NuGet. <img src="https://alexanderdevelopment.net/content/images/2017/08/chrome_2017-08-09_12-40-10.png#img-thumbnail" alt="Running Dynamics 365 Configuration Data Mover jobs in Azure Functions"></p>
<p>Here is the content of the file so you can copy and paste:</p>
<pre><code>{
  &quot;frameworks&quot;: {
    &quot;net46&quot;:{
      &quot;dependencies&quot;: {
        &quot;Microsoft.CrmSdk.CoreAssemblies&quot;: &quot;8.2.0&quot;,
        &quot;Microsoft.CrmSdk.XrmTooling.CoreAssembly&quot;: &quot;8.2.0&quot;,
        &quot;log4net&quot;: &quot;2.0.8&quot;
      }
    }
  }
}
</code></pre>
<p>Finally, you need to update the function code in the run.csx file. <img src="https://alexanderdevelopment.net/content/images/2017/08/chrome_2017-08-09_13-10-11.png#img-thumbnail" alt="Running Dynamics 365 Configuration Data Mover jobs in Azure Functions"></p>
<p>Here's the code you can use:</p>
<pre><code>#r &quot;NewtonSoft.Json&quot;
#r &quot;AlexanderDevelopment.ConfigDataMover.Lib.dll&quot;
using System.Net;
using System.Collections.Generic;
using AlexanderDevelopment.ConfigDataMover.Lib;
using System.Xml;

static string _sourceString = null;
static string _targetString = null;
static bool _mapBaseBu = false;
static bool _mapBaseCurrency = false;
static List&lt;GuidMapping&gt; _guidMappings = new List&lt;GuidMapping&gt;();
static List&lt;JobStep&gt; _jobSteps = new List&lt;JobStep&gt;();

public static async Task&lt;HttpResponseMessage&gt; Run(HttpRequestMessage req, TraceWriter log)
{
    log.Info(&quot;C# HTTP trigger function processed a request.&quot;);

    // parse query parameters
    string jobdata = req.GetQueryNameValuePairs()
        .FirstOrDefault(q =&gt; string.Compare(q.Key, &quot;jobdata&quot;, true) == 0)
        .Value;
    string sourceparam = req.GetQueryNameValuePairs()
        .FirstOrDefault(q =&gt; string.Compare(q.Key, &quot;source&quot;, true) == 0)
        .Value;
    string targetparam = req.GetQueryNameValuePairs()
        .FirstOrDefault(q =&gt; string.Compare(q.Key, &quot;target&quot;, true) == 0)
        .Value;

    if(jobdata == null)
    {
        return req.CreateResponse(HttpStatusCode.BadRequest, &quot;Please post jobdata&quot;);
    }
    else
    {
        ParseConfig(jobdata);
		
		//use source and target values if provided in the POST
		if(!string.IsNullOrEmpty(targetparam))
		{
			_targetString = targetparam;
		}
		if(!string.IsNullOrEmpty(sourceparam))
		{
			_sourceString = sourceparam;
		}
		
		//do some basic validations
		if (string.IsNullOrEmpty(_sourceString))
		{
			return req.CreateResponse(HttpStatusCode.BadRequest,&quot;no source connection specified - exiting&quot;);
		}
		if (string.IsNullOrEmpty(_targetString))
		{
			return req.CreateResponse(HttpStatusCode.BadRequest,&quot;no target connection specified - exiting&quot;);
		}
		if (!(_jobSteps.Count &gt; 0))
		{
			return req.CreateResponse(HttpStatusCode.BadRequest,&quot;no steps in job - exiting&quot;);
		}

		Importer importer = new Importer();
		importer.GuidMappings = _guidMappings;
		importer.JobSteps = _jobSteps;
		importer.SourceString = _sourceString; 
		importer.TargetString = _targetString; 
		importer.MapBaseBu = _mapBaseBu;
		importer.MapBaseCurrency = _mapBaseCurrency;
		importer.Process();

		int errorCount = importer.ErrorCount;

		importer = null;
		
		//show a message to the user
		if (errorCount == 0)
		{
			return req.CreateResponse(HttpStatusCode.OK,&quot;Job finished with no errors.&quot;);
		}
		else
		{
			return req.CreateResponse(HttpStatusCode.BadRequest,&quot;Job finished with errors.&quot;);
		}
    }
}

public static void ParseConfig(string jobdata)
{
    XmlDocument xml = new XmlDocument();
	xml.LoadXml(jobdata);
	_jobSteps.Clear();
	_guidMappings.Clear();

	XmlNodeList stepList = xml.GetElementsByTagName(&quot;Step&quot;);
	foreach (XmlNode xn in stepList)
	{
		JobStep step = new JobStep();
		step.StepName = xn.SelectSingleNode(&quot;Name&quot;).InnerText;
		step.StepFetch = xn.SelectSingleNode(&quot;Fetch&quot;).InnerText;
		step.UpdateOnly = false;
		if(xn.Attributes[&quot;updateOnly&quot;]!=null)
			step.UpdateOnly = Convert.ToBoolean(xn.Attributes[&quot;updateOnly&quot;].Value);

		step.CreateOnly = false;
		if (xn.Attributes[&quot;createOnly&quot;] != null)
			step.CreateOnly = Convert.ToBoolean(xn.Attributes[&quot;createOnly&quot;].Value);

		_jobSteps.Add(step);
	}

	XmlNodeList configData = xml.GetElementsByTagName(&quot;JobConfig&quot;);
	_mapBaseBu = Convert.ToBoolean(configData[0].Attributes[&quot;mapBuGuid&quot;].Value);
	_mapBaseCurrency = Convert.ToBoolean(configData[0].Attributes[&quot;mapCurrencyGuid&quot;].Value);

	XmlNodeList mappingList = xml.GetElementsByTagName(&quot;GuidMapping&quot;);
	foreach (XmlNode xn in mappingList)
	{
		Guid sourceGuid = new Guid(xn.Attributes[&quot;source&quot;].Value);
		Guid targetGuid = new Guid(xn.Attributes[&quot;target&quot;].Value);
		_guidMappings.Add(new GuidMapping { sourceId = sourceGuid, targetId = targetGuid });
	}
	XmlNodeList connectionNodes = xml.GetElementsByTagName(&quot;ConnectionDetails&quot;);
	if (connectionNodes.Count &gt; 0)
	{
		_sourceString = connectionNodes[0].Attributes[&quot;source&quot;].Value;
		_targetString = connectionNodes[0].Attributes[&quot;target&quot;].Value;
	}
}
</code></pre>
<h4 id="executingyourazurefunction">Executing your Azure Function</h4>
<p>To execute the function, you'll need to copy the function key so that you can send it as a POST parameter.<br>
<img src="https://alexanderdevelopment.net/content/images/2017/08/chrome_2017-08-09_12-43-21.png#img-thumbnail" alt="Running Dynamics 365 Configuration Data Mover jobs in Azure Functions"></p>
<p>Once you have that, you can build a POST request. Here's what it looks like in Postman:<br>
<img src="https://alexanderdevelopment.net/content/images/2017/08/Postman_2017-08-09_12-44-19-redacted.png#img-thumbnail" alt="Running Dynamics 365 Configuration Data Mover jobs in Azure Functions"></p>
<p>The only required parameters are &quot;code&quot; and &quot;jobdata.&quot; &quot;Code&quot; is the function key you copied earlier. &quot;Jobdata&quot; is the content of a Configuration Data Mover job XML file. If you do not have the source/target connection details saved in your &quot;jobdata&quot; XML, you will need to also include &quot;source&quot; and &quot;target&quot; connection string parameters in your request. If you do have connection details saved in the &quot;jobdata&quot; XML and you also supply &quot;source&quot; and &quot;target&quot; connection string parameters, they will be used instead of what is in the &quot;jobdata&quot; XML.</p>
<p>Assuming everything goes as expected, you should get a &quot;job finished with no errors&quot; response like this:<br>
<img src="https://alexanderdevelopment.net/content/images/2017/08/Postman_2017-08-09_12-45-11.png#img-thumbnail" alt="Running Dynamics 365 Configuration Data Mover jobs in Azure Functions"></p>
<p>If you still have the function editor interface open, you'll see new log entries like this:<br>
<img src="https://alexanderdevelopment.net/content/images/2017/08/chrome_2017-08-09_12-44-48.png#img-thumbnail" alt="Running Dynamics 365 Configuration Data Mover jobs in Azure Functions"></p>
<h4 id="caveats">Caveats</h4>
<ol>
<li>I originally built the Configuration Data Mover to use Apache log4net for detailed logging. The AlexanderDevelopment.ConfigDataMover.Lib library here is still trying to use log4net, but those log entries aren't going anywhere. I'll probably look into modifying the logging approach in the library so that it works better in situations where the library used like this. The upshot is that what I've outlined here will give you only a basic success/failure message.</li>
<li>Currently the AlexanderDevelopment.ConfigDataMover.Lib library can either connect to a live CRM instance or read configuration data from a JSON file that it can open. I have a future enhancement in mind that would allow for configuration data to be passed to the library to make it more flexible.</li>
</ol>
</div>]]></content:encoded></item><item><title><![CDATA[A Dynamics 365 local message listener for web client notifications - part 2]]></title><description><![CDATA[<div class="kg-card-markdown"><p>In <a href="https://alexanderdevelopment.net/post/2017/07/19/a-dynamics-365-local-message-listener-for-web-client-notifications-part-1">part one</a> of this series, I discussed an approach for passing notifications from local applications to the Dynamics 365 web client through a message listener process that runs on an end user's PC. Today I will show the code I used to build the message listener and the code</p></div>]]></description><link>https://alexanderdevelopment.net/post/2017/07/21/a-dynamics-365-local-message-listener-for-web-client-notifications-part-2/</link><guid isPermaLink="false">5a5837246636a30001b978cd</guid><category><![CDATA[Microsoft Dynamics CRM]]></category><category><![CDATA[Dynamics 365]]></category><category><![CDATA[integration]]></category><category><![CDATA[utilities]]></category><category><![CDATA[C#]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Lucas Alexander]]></dc:creator><pubDate>Fri, 21 Jul 2017 12:30:00 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p>In <a href="https://alexanderdevelopment.net/post/2017/07/19/a-dynamics-365-local-message-listener-for-web-client-notifications-part-1">part one</a> of this series, I discussed an approach for passing notifications from local applications to the Dynamics 365 web client through a message listener process that runs on an end user's PC. Today I will show the code I used to build the message listener and the code to consume notifications in Dynamics 365.</p>
<h4 id="themessagelistener">The message listener</h4>
<p>My message listener is a lightweight web server built in C# using the &quot;WebServer&quot; class from this <a href="https://codehosting.net/blog/BlogEngine/post/Simple-C-Web-Server">blog post</a>.</p>
<p>I've made a couple of small modifications to the original web server code to enable cross-origin resource sharing (CORS). Otherwise requests from the Dynamics 365 web resource would fail because the sites have different origins. Here's my updated WebServer class:</p>
<pre><code>/*
 * The MIT License (MIT)
 * 
 * Copyright (c) 2013 David's Blog (www.codehosting.net) 
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 
 * associated documentation files (the &quot;Software&quot;), to deal in the Software without restriction, 
 * including without limitation the rights to use, copy, modify, merge, publish, distribute, 
 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all copies or 
 * substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 
 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 
 * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 
 * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
 * DEALINGS IN THE SOFTWARE.
*/

//The code below is mostly taken from https://codehosting.net/blog/BlogEngine/post/Simple-C-Web-Server
//I've added the headers to enable CORS requests.

using System;
using System.Net;
using System.Threading;
using System.Linq;
using System.Text;

namespace SimpleWebServer
{
    public class WebServer
    {
        private readonly HttpListener _listener = new HttpListener();
        private readonly Func&lt;HttpListenerRequest, string&gt; _responderMethod;

        public WebServer(string[] prefixes, Func&lt;HttpListenerRequest, string&gt; method)
        {
            if (!HttpListener.IsSupported)
                throw new NotSupportedException(
                    &quot;Needs Windows XP SP2, Server 2003 or later.&quot;);

            // URI prefixes are required, for example 
            // &quot;http://localhost:8080/index/&quot;.
            if (prefixes == null || prefixes.Length == 0)
                throw new ArgumentException(&quot;prefixes&quot;);

            // A responder method is required
            if (method == null)
                throw new ArgumentException(&quot;method&quot;);

            foreach (string s in prefixes)
                _listener.Prefixes.Add(s);

            _responderMethod = method;
            _listener.Start();
        }

        public WebServer(Func&lt;HttpListenerRequest, string&gt; method, params string[] prefixes)
            : this(prefixes, method) { }

        public void Run()
        {
            ThreadPool.QueueUserWorkItem((o) =&gt;
            {
                //Console.WriteLine(&quot;Webserver running...&quot;);
                try
                {
                    while (_listener.IsListening)
                    {
                        ThreadPool.QueueUserWorkItem((c) =&gt;
                        {
                            var ctx = c as HttpListenerContext;
                            try
                            {
                                string rstr = _responderMethod(ctx.Request);
                                byte[] buf = Encoding.UTF8.GetBytes(rstr);
                                if (ctx.Request.HttpMethod == &quot;OPTIONS&quot;)
                                {
                                    ctx.Response.AddHeader(&quot;Access-Control-Allow-Headers&quot;, &quot;Content-Type, Accept, X-Requested-With&quot;);
                                    ctx.Response.AddHeader(&quot;Access-Control-Allow-Methods&quot;, &quot;GET, POST&quot;);
                                    ctx.Response.AddHeader(&quot;Access-Control-Max-Age&quot;, &quot;1728000&quot;);
                                }
                                ctx.Response.AddHeader(&quot;Access-Control-Allow-Origin&quot;, &quot;*&quot;);
                                ctx.Response.ContentLength64 = buf.Length;
                                ctx.Response.OutputStream.Write(buf, 0, buf.Length);
                            }
                            catch { } // suppress any exceptions
                            finally
                            {
                                // always close the stream
                                ctx.Response.OutputStream.Close();
                            }
                        }, _listener.GetContext());
                    }
                }
                catch { } // suppress any exceptions
            });
        }

        public void Stop()
        {
            _listener.Stop();
            _listener.Close();
        }
    }
}
</code></pre>
<p>Here is the code for a proof-of-concept application that runs the listener web server. It allows you to enter messages directly on the command line for easy testing, but ideally you would configure your message listener to run as a service or in some other mostly headless fashion. You will need the <a href="http://www.newtonsoft.com/json">JSON.Net</a> library to compile this code.</p>
<pre><code>using System;
using System.Collections.Generic;
using System.Net;
using SimpleWebServer;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace CrmIntegrationServer
{
    class Program
    {
        static List&lt;string&gt; _messages;

        static void Main(string[] args)
        {
            _messages = new List&lt;string&gt;();
            WebServer ws = new WebServer(ProcessRequest, &quot;http://localhost:8080/&quot;);
            ws.Run();
            Console.WriteLine(&quot;Demo CRM integration server. Type 'CTRL+C' to exit.&quot;);
            while (true)
            {
                Console.WriteLine(&quot;Enter your message:&quot;);
                string receivedline = Console.ReadLine();
                _messages.Add(&quot;{\&quot;data\&quot;:\&quot;&quot;+receivedline+&quot;\&quot;}&quot;);
            }
        }

        public static string ProcessRequest(HttpListenerRequest request)
        {
            string receviedmessage = string.Empty;
            string response = string.Empty;
            if (request.HasEntityBody)
            {
                using (System.IO.Stream body = request.InputStream) // here we have data
                {
                    using (System.IO.StreamReader reader = new System.IO.StreamReader(body, request.ContentEncoding))
                    {
                        receviedmessage = reader.ReadToEnd();
                    }
                    JObject reqobject = JObject.Parse(receviedmessage);
                    switch (reqobject.Value&lt;string&gt;(&quot;action&quot;).ToUpper())
                    {
                        case &quot;QUEUE&quot;:
                            string messagebody = reqobject[&quot;messagebody&quot;].ToString(Formatting.None);
                            _messages.Add(messagebody);
                            response =  &quot;{\&quot;result\&quot;:\&quot;success\&quot;}&quot;;
                            break;
                        case &quot;READ&quot;:
                            response = JsonConvert.SerializeObject(_messages);
                            _messages.Clear();
                            break;
                    }
                }
            }
            return response;
        }
    }
}
</code></pre>
<h4 id="thedynamics365clientjavascript">The Dynamics 365 client JavaScript</h4>
<p>Finally, here's the code for the Dynamics 365 web resource that reads the messages. I have it set to poll for new messages every 100 milliseconds, which seems plenty fast, but you can experiment to find the value that works best for you. Because it's just making local requests and not putting additional load on your Dynamics 365 org, you don't need to worry about negatively impacting performance.</p>
<pre><code>&lt;html&gt;  
&lt;head&gt;  
    &lt;title&gt;listener demo &lt;/title&gt;
    &lt;script src=&quot;ClientGlobalContext.js.aspx&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;
    &lt;script src=&quot;https://code.jquery.com/jquery-2.2.4.min.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;
    &lt;script&gt;
	var intervalId = null;
	var openrequest = false;
	var requestData = function(){
		if(!openrequest){
			openrequest = true;
			var request = $.ajax({
				url: 'http://localhost:8080',
				type: 'POST',
				contentType: 'application/json',
				dataType: &quot;json&quot;,
				data: JSON.stringify({action:'read'})
			});
			request.done(function( msg ) {
				openrequest = false;
				for(var i=0;i&lt;msg.length;i++){
					$('#messageDiv').append(JSON.parse(msg[i]).data + '&lt;br /&gt;')
				}
			});
			request.fail(function( jqXHR, textStatus ) {
				openrequest = false;
				clearInterval(intervalId);
				$('#messageDiv').append('Request failed: ' + textStatus );
			});
		}
	}
	var intervaltime = 100;
	$(function(){
		intervalId = setInterval(requestData, intervaltime);
    });
	
    &lt;/script&gt;
&lt;/head&gt;  
&lt;body&gt;  
	&lt;div id='messageDiv' /&gt;
&lt;/body&gt;  
&lt;/html&gt;
</code></pre>
<h4 id="finalthoughts">Final thoughts</h4>
<ol>
<li>You could modify the my proof-of-concept listener application to support outbound integrations with local workstation resources. For example, if you want to start a local program based on a Dynamics 365 form event, you post a specific kind of JSON request to the listener from Dynamics 365, and then the listener would start the program running.</li>
<li>Keeping the queued messages as a list of strings is probably not be the best long-term approach, especially if you have different types of messages passing through the listener that you want to handle differently. In that case, you'd want to store the messages in a data structure that allows you to retrieve just a particular kind of message.</li>
<li>The list of queued messages in my proof-of-concept application does not persist if the listener process stops running. This probably isn't a big deal because the whole idea of the message listener is to facilitate real-time communication, but I wanted to make the point explicitly clear.</li>
</ol>
<p>What do you think about this approach? Can you see yourself using it on your projects? Let us know in the comments!</p>
</div>]]></content:encoded></item><item><title><![CDATA[A Dynamics 365 local message listener for web client notifications - part 1]]></title><description><![CDATA[<div class="kg-card-markdown"><p>One problem that comes up from time to time on Dynamics 365 Customer Engagement projects is how to receive notifications from an application running on a user's local PC. Although the <a href="https://msdn.microsoft.com/en-US/library/dn865015(v=crm.10).aspx">Unified Service Desk</a> (USD) interface supports a variety of ways for Dynamics 365 to interact with local applications, the</p></div>]]></description><link>https://alexanderdevelopment.net/post/2017/07/19/a-dynamics-365-local-message-listener-for-web-client-notifications-part-1/</link><guid isPermaLink="false">5a5837246636a30001b978c2</guid><category><![CDATA[Microsoft Dynamics CRM]]></category><category><![CDATA[Dynamics 365]]></category><category><![CDATA[integration]]></category><category><![CDATA[utilities]]></category><dc:creator><![CDATA[Lucas Alexander]]></dc:creator><pubDate>Wed, 19 Jul 2017 23:16:41 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p>One problem that comes up from time to time on Dynamics 365 Customer Engagement projects is how to receive notifications from an application running on a user's local PC. Although the <a href="https://msdn.microsoft.com/en-US/library/dn865015(v=crm.10).aspx">Unified Service Desk</a> (USD) interface supports a variety of ways for Dynamics 365 to interact with local applications, the out-of-the-box web interface does not. Today, I will present an approach that uses something similar to the Dynamics 365 USD <a href="https://msdn.microsoft.com/en-us/library/dn864961.aspx">generic listener adapter</a>.</p>
<p>The USD generic listener adapter is essentially just a lightweight web server that runs on the local workstation. When it receives GET requests with certain query string parameters, it raises events in the USD application that trigger various predefined actions. It was originally intended for testing CTI configuration in USD, and although Microsoft officially calls it a &quot;testing tool,&quot; it's actually an easy-to-use (and free) component that you can use to trigger all sorts of automations in USD.</p>
<h4 id="awebclientmessagelistener">A web client message listener</h4>
<p>My approach to a message listener for the web client also uses a lightweight web server built in C# that runs on the local workstation. When an application wants to pass a message to Dynamics 365, it can post a JSON object to the listener, where it will be queued for later retrieval by custom JavaScript code in Dynamics 365. When the queued messages are retrieved from the listener, they are also purged from the queue so each request returns only new messages.</p>
<p>Here's what the JSON objects look like:</p>
<pre><code>//POSTING A NEW MESSAGE
{
  &quot;action&quot;:&quot;queue&quot;,
  &quot;messagebody&quot;:{
      &quot;data&quot;:&quot;MESSAGE TO PASS TO CRM . . .&quot;
  }
}

//REQUESTING QUEUED MESSAGES
{
  &quot;action&quot;:&quot;read&quot;
}

//QUEUED MESSAGES
[
  {&quot;data&quot;:&quot;MESSAGE FOR CRM 1&quot;},
  {&quot;data&quot;:&quot;MESSAGE FOR CRM 2&quot;},
  {&quot;data&quot;:&quot;MESSAGE FOR CRM 3&quot;}
]
</code></pre>
<p>Once the messages are retrieved in Dynamics 365, they can be processed however you like. In my next post, I'll show the code to make the approach work. Until then, happy coding!</p>
</div>]]></content:encoded></item><item><title><![CDATA[Updated Dynamics 365 Configuration Data Mover to support new online regions]]></title><description><![CDATA[<div class="kg-card-markdown"><p>About two weeks ago a commenter mentioned that my Configuration Data Mover wasn't working with UK Dynamics 365 online organizations that had been created since the change to the <em>orgname.crm11.dynamics.com</em> URL structure. I've released a new version with an updated SDK reference that has resolved the issue.</p></div>]]></description><link>https://alexanderdevelopment.net/post/2017/07/12/updated-dynamics-365-configuration-data-mover-to-support-new-online-regions/</link><guid isPermaLink="false">5a5837246636a30001b978c7</guid><category><![CDATA[Microsoft Dynamics CRM]]></category><category><![CDATA[Dynamics 365]]></category><category><![CDATA[Configuration Data Mover]]></category><category><![CDATA[integration]]></category><category><![CDATA[utilities]]></category><dc:creator><![CDATA[Lucas Alexander]]></dc:creator><pubDate>Wed, 12 Jul 2017 15:17:30 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p>About two weeks ago a commenter mentioned that my Configuration Data Mover wasn't working with UK Dynamics 365 online organizations that had been created since the change to the <em>orgname.crm11.dynamics.com</em> URL structure. I've released a new version with an updated SDK reference that has resolved the issue.</p>
<p>If you are using an older version of the data mover and you are working with online orgs in a <a href="https://technet.microsoft.com/en-us/library/dn956534.aspx">new region</a>, you may want to go ahead and upgrade to the latest version <a href="https://github.com/lucasalexander/AlexanderDevelopment.ConfigDataMover/releases/tag/v2.1.6393.21981">here</a>.</p>
</div>]]></content:encoded></item><item><title><![CDATA[Updated version of Dynamics 365/CRM Deployment Wizard]]></title><description><![CDATA[<div class="kg-card-markdown"><p>I've released an updated version of my Dynamics CRM Deployment Wizard that supports Dynamics 365. The Deployment Wizard is designed to automate your solution deployments much like the <a href="https://msdn.microsoft.com/en-us/library/dn688182.aspx">SDK's Dynamics CRM Package Deployer</a>, but while the SDK tool requires you to build a deployment package using Visual Studio, my Deployment</p></div>]]></description><link>https://alexanderdevelopment.net/post/2017/03/22/updated-version-of-dynamics-365-crm-deployment-wizard/</link><guid isPermaLink="false">5a5837246636a30001b978a5</guid><category><![CDATA[Microsoft Dynamics CRM]]></category><category><![CDATA[Dynamics 365]]></category><category><![CDATA[utilities]]></category><category><![CDATA[CRM Deployment Wizard]]></category><dc:creator><![CDATA[Lucas Alexander]]></dc:creator><pubDate>Wed, 22 Mar 2017 20:15:15 GMT</pubDate><media:content url="https://alexanderdevelopment.net/content/images/2017/03/Dynamics-CRM-Deployment-Wizard_header.png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://alexanderdevelopment.net/content/images/2017/03/Dynamics-CRM-Deployment-Wizard_header.png" alt="Updated version of Dynamics 365/CRM Deployment Wizard"><p>I've released an updated version of my Dynamics CRM Deployment Wizard that supports Dynamics 365. The Deployment Wizard is designed to automate your solution deployments much like the <a href="https://msdn.microsoft.com/en-us/library/dn688182.aspx">SDK's Dynamics CRM Package Deployer</a>, but while the SDK tool requires you to build a deployment package using Visual Studio, my Deployment Wizard tool only requires you to create a simple JSON manifest file. The manifest lists:</p>
<ol>
<li>The solutions you want to deploy</li>
<li>Any <a href="https://alexanderdevelopment.net/tag/configuration-data-mover/">Configuration Data Mover</a> jobs you</li>
<li>Any system commands you want to execute as part of your overall deployment process.</li>
</ol>
<p>Here's a <a href="https://alexanderdevelopment.net/post/2016/05/05/introducing-the-dynamics-crm-deployment-wizard/">link</a> to the original blog post that discusses the Deployment Wizard in greater detail. The one thing to keep in mind is that this updated version uses <a href="https://msdn.microsoft.com/en-us/library/mt608573.aspx">XRM tooling connection strings</a> as opposed to the the <a href="https://msdn.microsoft.com/en-us/library/gg695810(v=crm.7).aspx">simplified CRM connection strings</a> used in the previous version. Other than that, everything else is basically the same.</p>
<h3 id="gettingthedynamicscrmdeploymentwizard">Getting the Dynamics CRM Deployment Wizard</h3>
<p>The source code is available in my GitHub repository <a href="https://github.com/lucasalexander/AlexanderDevelopment.CrmDeploymentWizard">here</a>.</p>
<p>A compiled version can be downloaded <a href="https://github.com/lucasalexander/AlexanderDevelopment.CrmDeploymentWizard/releases">here</a>.</p>
</div>]]></content:encoded></item><item><title><![CDATA[Dynamics 365 Configuration Data Mover v2.1]]></title><description><![CDATA[<div class="kg-card-markdown"><p>I've released an updated version of my popular CRM Configuration Data Mover utility that includes the following features:</p>
<ul>
<li>Steps can now be set as create-only, update-only or create+update.</li>
<li>You can browse to data files using a standard file open dialog window.</li>
</ul>
<p>This upgrade is fully compatible with existing job</p></div>]]></description><link>https://alexanderdevelopment.net/post/2017/03/17/dynamics-365-configuration-data-mover-v2-1/</link><guid isPermaLink="false">5a5837246636a30001b9789f</guid><category><![CDATA[Microsoft Dynamics CRM]]></category><category><![CDATA[Dynamics 365]]></category><category><![CDATA[Configuration Data Mover]]></category><category><![CDATA[integration]]></category><category><![CDATA[utilities]]></category><dc:creator><![CDATA[Lucas Alexander]]></dc:creator><pubDate>Fri, 17 Mar 2017 21:33:47 GMT</pubDate><media:content url="https://alexanderdevelopment.net/content/images/2017/03/AlexanderDevelopment-ConfigDataMover_2017-03-17_16-27-57.png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://alexanderdevelopment.net/content/images/2017/03/AlexanderDevelopment-ConfigDataMover_2017-03-17_16-27-57.png" alt="Dynamics 365 Configuration Data Mover v2.1"><p>I've released an updated version of my popular CRM Configuration Data Mover utility that includes the following features:</p>
<ul>
<li>Steps can now be set as create-only, update-only or create+update.</li>
<li>You can browse to data files using a standard file open dialog window.</li>
</ul>
<p>This upgrade is fully compatible with existing job files.</p>
<h4 id="gettingthedynamics365configurationdatamover">Getting the Dynamics 365 Configuration Data Mover</h4>
<p>The source code is available in my GitHub repository <a href="https://github.com/lucasalexander/AlexanderDevelopment.ConfigDataMover">here</a>.</p>
<p>A compiled version can be downloaded <a href="https://github.com/lucasalexander/AlexanderDevelopment.ConfigDataMover/releases">here</a>.</p>
</div>]]></content:encoded></item><item><title><![CDATA[Dynamics 365 Configuration Data Mover v2.0.1.2]]></title><description><![CDATA[<div class="kg-card-markdown"><p>I've released an updated version of my popular CRM Configuration Data Mover utility that fixes a small annoyance in the previous version where you could open multiple instances of the set connection, about and check for upgrade windows. This upgrade is fully compatible with existing job files.</p>
<h4 id="gettingthedynamics365configurationdatamover">Getting the Dynamics</h4></div>]]></description><link>https://alexanderdevelopment.net/post/2017/02/27/dynamics-crm-configuration-data-mover-v2-0-1-2/</link><guid isPermaLink="false">5a5837246636a30001b97899</guid><category><![CDATA[Microsoft Dynamics CRM]]></category><category><![CDATA[Dynamics 365]]></category><category><![CDATA[Configuration Data Mover]]></category><category><![CDATA[integration]]></category><category><![CDATA[utilities]]></category><dc:creator><![CDATA[Lucas Alexander]]></dc:creator><pubDate>Mon, 27 Feb 2017 22:35:20 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p>I've released an updated version of my popular CRM Configuration Data Mover utility that fixes a small annoyance in the previous version where you could open multiple instances of the set connection, about and check for upgrade windows. This upgrade is fully compatible with existing job files.</p>
<h4 id="gettingthedynamics365configurationdatamover">Getting the Dynamics 365 Configuration Data Mover</h4>
<p>The source code is available in my GitHub repository <a href="https://github.com/lucasalexander/AlexanderDevelopment.ConfigDataMover">here</a>.</p>
<p>A compiled version can be downloaded <a href="https://github.com/lucasalexander/AlexanderDevelopment.ConfigDataMover/releases">here</a>.</p>
</div>]]></content:encoded></item><item><title><![CDATA[Dynamics 365 Configuration Data Mover v2.0]]></title><description><![CDATA[<div class="kg-card-markdown"><p>I've released an updated version of my popular CRM Configuration Data Mover utility. This version now supports Dynamics 365 and has an updated GUI built with Windows Presentation Foundation that replaces the previous Windows Forms GUI.</p>
<p>Jobs that were created with earlier versions of the tool will work with this</p></div>]]></description><link>https://alexanderdevelopment.net/post/2017/02/04/dynamics-365-configuration-data-mover-v2-0/</link><guid isPermaLink="false">5a5837246636a30001b97883</guid><category><![CDATA[Microsoft Dynamics CRM]]></category><category><![CDATA[Dynamics 365]]></category><category><![CDATA[integration]]></category><category><![CDATA[utilities]]></category><category><![CDATA[Configuration Data Mover]]></category><dc:creator><![CDATA[Lucas Alexander]]></dc:creator><pubDate>Sun, 05 Feb 2017 04:31:37 GMT</pubDate><media:content url="https://alexanderdevelopment.net/content/images/2017/02/AlexanderDevelopment-ConfigDataMover_2017-02-04_22-16-33.png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://alexanderdevelopment.net/content/images/2017/02/AlexanderDevelopment-ConfigDataMover_2017-02-04_22-16-33.png" alt="Dynamics 365 Configuration Data Mover v2.0"><p>I've released an updated version of my popular CRM Configuration Data Mover utility. This version now supports Dynamics 365 and has an updated GUI built with Windows Presentation Foundation that replaces the previous Windows Forms GUI.</p>
<p>Jobs that were created with earlier versions of the tool will work with this version, but you will have to update your CRM connection parameters to specify the authorization type - Active Directory, IFD or Office 365.<br>
<img src="https://alexanderdevelopment.net/content/images/2017/02/AlexanderDevelopment-ConfigDataMover_2017-02-04_22-00-56.png#img-thumbnail" alt="Dynamics 365 Configuration Data Mover v2.0"></p>
<p>The other main change in the client is the way GUID mappings are entered. GUIDs are now entered in a text box with each mapping on a separate line. A &quot;-&gt;&quot; is used to separate source and target. The screenshot below shows the new UI.<br>
<img src="https://alexanderdevelopment.net/content/images/2017/02/AlexanderDevelopment-ConfigDataMover_2017-02-04_22-09-14.png#img-thumbnail" alt="Dynamics 365 Configuration Data Mover v2.0"></p>
<h4 id="gettingthedynamicscrmconfigurationdatamover">Getting the Dynamics CRM Configuration Data Mover</h4>
<p>The source code is available in my GitHub repository <a href="https://github.com/lucasalexander/AlexanderDevelopment.ConfigDataMover">here</a>.</p>
<p>A compiled version can be downloaded <a href="https://github.com/lucasalexander/AlexanderDevelopment.ConfigDataMover/releases">here</a>.</p>
<p>Please let me know what you think of this new version in the comments section below.</p>
</div>]]></content:encoded></item><item><title><![CDATA[Easy dependent picklists for Dynamics CRM]]></title><description><![CDATA[<div class="kg-card-markdown"><p>I've created a new solution for creating dependent picklists on Dynamics CRM forms that requires no coding to implement. You can download it from my Crm-Sample-Code GitHub <a href="https://github.com/lucasalexander/Crm-Sample-Code">repository</a> here: <a href="https://raw.githubusercontent.com/lucasalexander/Crm-Sample-Code/master/misc-code-samples/easydependentpicklists.js">https://raw.githubusercontent.com/lucasalexander/Crm-Sample-Code/master/misc-code-samples/easydependentpicklists.js</a></p>
<p>Assume you have three picklists with related options like in the</p></div>]]></description><link>https://alexanderdevelopment.net/post/2016/10/06/easy-dependent-picklists-for-dynamics-crm/</link><guid isPermaLink="false">5a5837246636a30001b9784a</guid><category><![CDATA[Microsoft Dynamics CRM]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[utilities]]></category><dc:creator><![CDATA[Lucas Alexander]]></dc:creator><pubDate>Thu, 06 Oct 2016 22:25:11 GMT</pubDate><media:content url="https://alexanderdevelopment.net/content/images/2016/10/chrome_2016-10-06_17-21-16.png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://alexanderdevelopment.net/content/images/2016/10/chrome_2016-10-06_17-21-16.png" alt="Easy dependent picklists for Dynamics CRM"><p>I've created a new solution for creating dependent picklists on Dynamics CRM forms that requires no coding to implement. You can download it from my Crm-Sample-Code GitHub <a href="https://github.com/lucasalexander/Crm-Sample-Code">repository</a> here: <a href="https://raw.githubusercontent.com/lucasalexander/Crm-Sample-Code/master/misc-code-samples/easydependentpicklists.js">https://raw.githubusercontent.com/lucasalexander/Crm-Sample-Code/master/misc-code-samples/easydependentpicklists.js</a></p>
<p>Assume you have three picklists with related options like in the list below:</p>
<ul>
<li>lpa_level1picklist</li>
<li>1</li>
<li>2</li>
<li>lpa_level2picklist</li>
<li>1a</li>
<li>1b</li>
<li>2a</li>
<li>2b</li>
<li>lpa_level3picklist</li>
<li>1a1</li>
<li>1a2</li>
<li>1b1</li>
<li>2a1</li>
</ul>
<p>You can represent a tree of possible options like this:<br>
1 -&gt; 1a -&gt; 1a1<br>
1 -&gt; 1a -&gt; 1a2<br>
1 -&gt; 1b -&gt; 1b1<br>
2 -&gt; 2a -&gt; 2a1<br>
2 -&gt; 2a -&gt; 1a1<br>
2 -&gt; 2b</p>
<p>Should notice two important points:</p>
<ol>
<li>You don't have to have an equal number of options in each path. For example, under 2 -&gt; 2b, there are no children. In this case the new_level3 picklist should show no options when 2 -&gt; 2b is selected in the two parent picklists.</li>
<li>The same child can appear in multiple option paths. That is, level 3's &quot;1a1&quot; is a child of both &quot;1a&quot; and &quot;2a.&quot;</li>
</ol>
<p>To implement this filtering functionality on a CRM form, you just need to add my JavaScript file to your solution as a web resource and then call its initializePicklistFilter function when you want to apply the filtering. This could be in the form onload event or at any other time it makes sense.</p>
<p>The initializePicklistFilter function takes three input parameters:</p>
<ol>
<li>
<p>picklists - A pipe-delimited string that contains the picklists in the hierarchy in order of first parent to last child.<br>
Example: &quot;lpa_level1picklist|lpa_level2picklist|lpa_level3picklist&quot;</p>
</li>
<li>
<p>separator - String of characters used to separate levels in the parent-child option paths. This can be any string you like.<br>
Example: &quot; -&gt; &quot;</p>
</li>
<li>
<p>optionTree - An array of strings containing all possible parent-child option paths you want to enable on the form.<br>
Example: [&quot;1 -&gt; 1a -&gt; 1a1&quot;,&quot;1 -&gt; 1a -&gt; 1a2&quot;,&quot;1 -&gt; 1b -&gt; 1b1&quot;,&quot;2 -&gt; 2a -&gt; 2a1&quot;,&quot;2 -&gt; 2a -&gt; 1a1&quot;,&quot;2 -&gt; 2b&quot;]</p>
</li>
</ol>
<p>Putting it all together, your call to initializePicklistFilter for this example would look like this:</p>
<pre><code>initializePicklistFilter(
  &quot;lpa_level1picklist|lpa_level2picklist|lpa_level3picklist&quot;,
  &quot;-&gt;&quot;,
  [&quot;1 -&gt; 1a -&gt; 1a1&quot;,
    &quot;1 -&gt; 1a -&gt; 1a2&quot;,
    &quot;1 -&gt; 1b -&gt; 1b1&quot;,
    &quot;2 -&gt; 2a -&gt; 2a1&quot;,
    &quot;2 -&gt; 2a -&gt; 1a1&quot;,
    &quot;2 -&gt; 2b&quot;]
);
</code></pre>
<p>Here are a few points to consider:</p>
<ol>
<li>My code is based on the optionset labels, so it does not automatically support multiple languages. If you need to handle multiple languages, you would need to create a separate option tree array for each language and then call the initializePicklistFilter function with the corresponding array depending for the user's language.</li>
<li>Because the initializePicklistFilter call can be executed any time you want (and even at multiple times for the same set of pickilists on a form), you can dynamically modify the options based on external criteria. For example, you could use this to create different possible selection rules based on user roles.</li>
<li>My example uses a three-level picklist hierarchy, but this solution works for any number of picklists.</li>
<li>To apply picklist filters for multiple groups of picklists on the same form, just call the initializePicklistFilter multiple times with different parameters.</li>
<li>The chaining all possible paths through the option tree can make the initializePicklistFilter call unwieldy for picklists with lots of options. If your child options only depend on their immediate parents, you can chain together multiple initializePicklistFilter calls. That is, you can call it for the first parent and first child, then call it again for the first child and its first child, then that child and its child, etc.</li>
</ol>
<p>That's all for now. If you use this solution or have any thoughts, I'd love to hear about it in the comments.</p>
</div>]]></content:encoded></item></channel></rss>