Tag Archives: crm

Modifying Entity Icons the Quick Way in Microsoft CRM

Need to apply a bunch of icons to your custom entities in Microsoft CRM?  Here’s a shortcut for you, using the awesome XRM Toolbox…

First, get your hands on the XRM Toolbox (which now supports CRM 2013 as well).

Next, boot it up and click the Connect to CRM button:


(note: if you don’t see the apps listed on the home screen like they are in the screenshot above you will need to go back to the program folder and right-click on each DLL and unblock each file).

Ok, so first step is to upload some icons. 

Here, I typically pinch from Microsoft.  I go to an on premise installation of CRM and rob the image files from the crmweb folder.   Here’s some of the icons from my CRM 2013 server:

(from:  C:\Program Files\Microsoft Dynamics CRM\CRMWeb\_imgs\Ribbon)


To get these into CRM as Web Resources I use the XRM Toolbox’s Web Resources Manager:


I go to the File menu and select Load Web resources:


I browse to my folder and my files appear:


(I’ve pre-selected some that I want prior to this step and renamed them to match my entities)

Last step for these icons is to select the files I want and then from the CRM menu select the “Update, publish and add to solution” option:


Cool, that’s all my Web Resources created. Now, to apply them to my custom entities I launch XRM Toolbox’s ICONATOR !!!


This is another simple to use app.  You click the Load button:


And then its just a case of joining the dots.  Select your entity, select the icon you want and then click Map.  Do this once for the 16×16 image and then again for the 32×32 icon.  Repeat for each entity:


And then finally click Apply and Publish:


This is pretty quick stuff. XRM Toolbox is a great tool. 


Reusable Jscript Library of Common Functions for CRM 2011

I find myself needing the same jscript over and over again when I build out demos.  To make life easier I decided to create a function library that I can attach to any CRM form.  Here it is.  I will add to this over time. 

If you have any useful functions that should be included post them in the comments and I’ll incorporate them.  The jscript is available here and below.   At the end of this post you will see some examples demonstrating the use of these functions.

Warning: these functions are of a ‘demo’ standard, and should be hardened and tested before used in a production setting.

p.s. my older jscript reference post has been updated recently as well, check it out.

// Determine Form Type
// example: GetFormType();
function GetFormType() {
    var FormType = Xrm.Page.ui.getFormType();
    if (FormType != null) {
        switch (FormType) {
            case 1:
                return "create";
            case 2:
                return "update";
            case 3:
                return "readonly";
            case 4:
                return "disabled";
            case 6:
                return "bulkedit";
                return null;

// Show/Hide a TAB
// example: HideShowTab("General", false);   // "false" = invisible
function HideShowTab(tabName, visible) {
    try {
    catch (err) { }

// Show/Hide a SECTION
// example: HideShowSection("General", "Customers", false);   // "false" = invisible
function HideShowSection(tabName, sectionName, visible) {
    try {
    catch (err) { }

// Get GUID value of Lookup Field
// example GetGUIDofLookup("primarycontactid");
function GetGUIDofLookup(fieldname) {
    if (Xrm.Page.data.entity.attributes.get(fieldname).getValue() != null) {
        return Xrm.Page.data.entity.attributes.get(fieldname).getValue()[0].id;
    else return null;

// Get Name value of Lookup Field
// example GetNameofLookup("primarycontactid");
function GetNameofLookup(fieldname) {
    if (Xrm.Page.data.entity.attributes.get(fieldname).getValue() != null) {
        return Xrm.Page.data.entity.attributes.get(fieldname).getValue()[0].name;
    else return null;

// Get Value of Text Field
// example GetTextField("telephone1");
function GetTextField(fieldname) {
    return Xrm.Page.data.entity.attributes.get(fieldname).getValue();

// Get Integer value of Option Set Field
// example GetOptionsetInteger("address1_addresstypecode");
function GetOptionsetInteger(fieldname) {
    return Xrm.Page.data.entity.attributes.get(fieldname).getValue();

// Get Text value of Option Set Field
// example GetOptionsetText("address1_addresstypecode");
function GetOptionsetText(fieldname) {
    if (Xrm.Page.data.entity.attributes.get(fieldname).getValue() != null) {
        return Xrm.Page.data.entity.attributes.get(fieldname).getSelectedOption().text;
    else return null;

// Get Database Value of a Bit Field
// example GetBitValue("telephone1");
function GetBitValue(fieldname) {
    return Xrm.Page.data.entity.attributes.get(fieldname).getValue();

// Get Database Value of a Date Field
// example GetDate("createdon");
function GetDate(fieldname) {
    return Xrm.Page.data.entity.attributes.get(fieldname).getValue();

// Sets the time portion of a date field (and sets the date to today if blank)
// Example: SetTime('new_date2', 8, 30);
function SetTime(attributeName, hour, minute) {
        var attribute = Xrm.Page.getAttribute(attributeName);
        if (attribute.getValue() == null) {
            attribute.setValue(new Date());
        attribute.setValue(attribute.getValue().setHours(hour, minute, 0));

// Converts a CRM date value into dd-mm-yyyy
// Example:     
//              var ReviewDate = Xrm.Page.data.entity.attributes.get(new_date2).getValue(); 
//              alert(FormatDate(ReviewDate));
function FormatDate(fieldname) {
    var d = Xrm.Page.data.entity.attributes.get(fieldname).getValue();
    if (d != null) {
        var curr_date = d.getDate();
        var curr_month = d.getMonth();
        curr_month++;  // getMonth() considers Jan month 0, need to add 1
        var curr_year = d.getFullYear();
        return curr_date + "-" + curr_month + "-" + curr_year;
    else return null;

// Compares a date to today's date
// Example:     
//              var ReviewDate = Xrm.Page.data.entity.attributes.get(new_date2).getValue(); 
//              alert(DateCompare(ReviewDate));
// Returns:  "future date", "date is in the past", or "date is today"
function DateCompare(dateinput) {
    var today = new Date();
    var today_date = today.getDate();
    var today_month = today.getMonth();
    var today_year = today.getFullYear();

    var dateinput_date = dateinput.getDate();
    var dateinput_month = dateinput.getMonth();
    var dateinput_year = dateinput.getFullYear();

    if (dateinput != null && dateinput_year > today_year) {  // future year
        return "future date";
    else if (dateinput != null && dateinput_year < today_year) {  // prior year
        return "date is in the past";
    else if (dateinput != null && dateinput_year == today_year && dateinput_month > today_month) { //current year, future month
        return "future date";
    else if (dateinput != null && dateinput_year == today_year && dateinput_month < today_month) { //current year, prior month
        return "date is in the past";
    else if (dateinput != null && dateinput_year == today_year && dateinput_month == today_month && dateinput_date > today_date) { //current year, current month, future date
        return "future date";
    else if (dateinput != null && dateinput_year == today_year && dateinput_month == today_month && dateinput_date < today_date) { //current year, current month, prior date
        return "date is in the past";
    else if (dateinput != null && dateinput_year == today_year && dateinput_month == today_month && dateinput_date == today_date) { //same date
        return "date is today";
    else {
        return null;

// Here's a few more courtesy of Paul Kreeck
///Gets the Attributes by its Name.
 GetAttributeByName: function (attributeName)
 return Xrm.Page.getAttribute(attributeName);

///Sets the attributes required level.
 ///Values: ‘none’, ‘required’, ‘recommended’
SetAttributeRequiredLevel: function (attributeName, level)
 var attribute = GetAttributeByName(attributeName);
 if (attribute != null)
 return attribute.setRequiredLevel(level);
 return null;
///Sets whether data from the attribute will be submitted when the record is saved.
 ///Values: ‘always’, ‘never’, ‘dirty’
SetAttributeSubmitMode: function (attributeName, submitMode)
 var attribute = GetAttributeByName(attributeName);
if (attribute != null)
 if (submitMode == “always” || submitMode == “never” || submitMode == “dirty”)
 throw “Invalid Submit Mode parameter”;


Here are some examples where I utilise the above functions:

function AccountFormOnLoad() {
    var FormType = GetFormType();
    alert("Form type: " + FormType);


    SetTime('new_date2', 8, 30);

    var FieldDate = GetDate("new_date2");
    if(FormType == "update") {
        alert("hiding General tab");
        HideShowTab("general", false);

        alert("UNhiding General tab");
        HideShowTab("general", true);

        alert("hiding address section on general tab");
        HideShowSection("general", "address", false);

        alert("UNhiding address section on general tab");
        HideShowSection("general", "address", true);

        alert("getting GUID of primary contact");

        alert("getting name of primary contact");

        alert("getting value of telephone1");

        alert("getting integer value of address type");

        alert("getting text value of address type");


To reference the jscript library on a CRM form add the shared function library web resource to the Form and then add a form-specific jscript library web resource after that.  It is in this second jscript file that your form logic will sit and where you will make function calls against the shared functions library:



To reference the jscript library within a  custom Ribbon button’s definition either;

simply reference the library on the form:


or, you can reference the library within the ribbon definition:

          <CommandDefinition Id="ActivityFeeds.Form.account.MainTab.ExportData.Test.Command">
            <EnableRules />
            <DisplayRules />
				<JavaScriptFunction Library="$WebResource:new_shared_functions.js" FunctionName="NaN" />
				<JavaScriptFunction Library="$WebResource:new_account_form_examples.js" FunctionName="AccountFormOnLoad" />


Note: you have to specify a Function name when you reference a jscript library so just use some dummy value like “NaN”

Building Custom Screens using Dialogs and Ribbon Buttons in CRM 2011

In this post I demonstrate how you can rapidly extend Microsoft CRM with custom screens in minutes, rather than hours or days. 

I will demonstrate a custom Lead Qualification screen by using a custom Ribbon button that pops a CRM Dialog and I will share a couple of tweaks that smarten up the user experience.

Microsoft have supplied with Microsoft CRM 2011 a Lead Qualification screen where you can qualify or disqualify a Lead and chose what records you want created:


However, this screen sits outside CRM’s supported extensibility model and sometimes fails to meet requirements. When you hit this scenario you can attempt an unsupported customisation to the screen, you can build a replacement screen, you can use form fields and plug-ins to manage the requirement or you can use a Dialog.  In this post I will demonstrate the Dialog solution and provide some guidance on how you can improve the user experience.

Here’s my scenario.  I have Leads for both existing Customers (Contacts) and for non-customers.  I want users to be able to qualify or disqualify leads.  When they qualify them I want the system to create an Opportunity against a Contact record.  For non-customer Leads, the Contact record should be auto-created.

In this scenario the out-of-the-box screen has these limitations:

  • The user can choose to have a new Account created (I never want this)
  • The user can chose to have a new Contact created, even when the Lead references an existing Contact (we could end up with duplicates)
  • The user can accidentally chose to not have an Opportunity created
  • The user has to reselect the Contact on this form if they wish to associate the Opportunity to an existing Contact (despite the Contact being referenced on the Lead)

Ok, so let’s jump to the solution so you can see whether you like this approach.   I have added a Button to the Lead form’s ribbon menu which pops a Dialog:


If the user selects “Convert Lead” an Opportunity is created, the Lead status is updated and the Lead form is refreshed.  If the Lead referenced an existing Contact then the Opportunity will be attached to that Contact, otherwise a new Contact is created.  

If the user select “Disqualify Lead” the Dialog will prompt them for a reason and then update and close the Lead and refresh the Lead form.

The advantage with this approach is it is a more controlled user experience.  We are not exposing the user to options we don’t want them to select and not asking them to perform any double keying.   And by creating a ribbon button and adding some jscript to auto-refresh the CRM form we get a much nicer user experience then an out-of-the-box  Dialog experience.

Here’s how I configured this…


The Dialog


The Dialog is quite simple.  It has 2 pages.  The 1st page you see in the screenshot above.  It asks a question and captures the response.   You’ll see from the Dialog definition below that I then have a condition statement and only proceed to the 2nd page if the user chose the  “Disqualify” option on the 1st page:


Next, the Dialog needs to take action.  

For Disqualified Leads, the Dialog updates the Status of the Lead based on the Disqualify Reason captured:


For Qualified Leads, the Dialog checks whether the Lead references an existing customer and then either just creates an Opportunity record or creates a Contact and an Opportunity, before finally closing the Lead:



The Button


I added the Ribbon button using the VisualRibbonEditor available on CodePlex.  I copied the icon path and display rule from the out-of-the-box Qualify button.  Here’s the Action definition for the button:

               <JavaScriptFunction FunctionName="LaunchDialog" Library="$WebResource:new_LaunchDialog">
                <CrmParameter Value="PrimaryItemIds"/>

I needed to pass the Lead record’s GUID to my function so you will see I registered a CrmParameter in my ribbon definition.  “PrimaryItemIds” will give you the GUID of the current record.


The Jscript


Here’s my LaunchDialog function that the button calls.  There’s also a supporting function which just ensures the Dialog launches centred on screen:

function LaunchDialog(sLeadID) {
    var DialogGUID = "128CEEDC-2763-4FA9-AB89-35BBB7D5517D";

    // Get the CRM URL 
    var serverUrl = Xrm.Page.context.getServerUrl();

    // Cater for URL differences between onpremise and online 
    if (serverUrl.match(/\/$/)) {
        serverUrl = serverUrl.substring(0, serverUrl.length - 1);

    serverUrl = serverUrl + "/cs/dialog/rundialog.aspx?DialogId=" + "{" + DialogGUID + "}" + "&EntityName=lead&ObjectId=" + sLeadID;
    PopupCenter(serverUrl, "mywindow", 400, 400);

function PopupCenter(pageURL, title, w, h) {
    var left = (screen.width / 2) - (w / 2);
    var top = (screen.height / 2) - (h / 2);
    var targetWin = window.showModalDialog(pageURL, title, 'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=no, copyhistory=no, width=' + w + ', height=' + h + ', top=' + top + ', left=' + left);

This function receives the Lead record’s GUID as a parameter (thanks to the ribbon definition) and combines that with the CRM Server URL (which is derived via Xrm.Page.context) and with the GUID of the Dialog definition (which is hardcoded) and then pops that URL.  It uses window.showModalDialog() and window.location.reload(true) to automatically refresh the Lead form when the Dialog closes.

Now I have hardcoded the GUID of the Dialog in my function.   A better solution would be to have that housed as a parameter and read at runtime.  Check out this post for an approach you can follow to implement that.

That’s it, I hope someone finds this useful. Smile


Upgrading Microsoft CRM 3.0 to CRM 2011

I am currently working on a CRM 3.0 to CRM 2011 upgrade.  Here are some thoughts on the process that have surfaced as we enter the planning phase…

  • An upgrade to CRM 2011 requires, in addition to the CRM software upgrade, a platform upgrade.  You should expect to be procuring new hardware to run the 64 bit Windows and SQL 2008 platforms.
  • The upgrade process requires you to upgrade ‘through’ CRM 4.0.  You don’t have to use CRM 4.0 but you will need to run the CRM 3.0 to CRM 4.0 upgrade and then upgrade to CRM 2011.
  • You will need to install CRM 4.0 over your CRM 3.0 instance to upgrade it, that is the only upgrade approach available between those versions.  If ‘losing’ your 3.0 environments is unacceptable then you will need additional environments.
  • Your upgrade platform needs to support both 3.0 and 4.0.  Windows 2003 SP2 and SQL 2005 SP3 is the level you need to be at.
  • CRM 2011 will be installed fresh on the new hardware platform.  The CRM database, once upgrade to 4.0, can be imported into the CRM 2011 instance to upgrade it to 2011.
  • Because of the ‘in-place upgrade’ approach required to upgrade from 3.0 to 4.0 it is worth considering whether you can image or snapshot the server prior to the upgrade so that the process is more easily repeatable.
  • You must utilise at least 1 (preferably 2 or more) non-production environments to work through the upgrade process.
  • You are upgrading both the data and the customisations to the system.  The upgrade ‘wizard’ provided by Microsoft takes care of the data but the customisations require refactoring and a bunch of testing.
  • Once you have completed the upgrade process a couple of times you should be confident with the process for upgrading the data.  You can now focus on the customisations.
  • Customisation changes back in the production 3.0 system must be put on strict hold for the duration of the project.  You don’t want to be upgrading in parallel with on going production changes.  And once you start doing an in-place upgrade in your dev and test environments you lose access to those environments for testing on going production changes.
  • Customisations should be re-factored and re-tested in your dev/test/uat environments.

The CRM 2011 production environment can be built in advance.  Once your refactored customisations are production ready and you are confident in the upgrade process you can execute the production deployment process:

      • Refresh the production database to a test environment (you will need a clean CRM 3.0 environment ready for this)
      • Run the in-place upgrade over that database on the test environment (we are deliberately avoiding changes to the production server so we can roll back to it if things go pear shaped)
      • Take the upgraded 4.0 version of your production database and import it into the new CRM 2011 production platform.
      • Deploy your re-factored customisations
      • Test
      • Resume production access

      Note: I’m avoiding steps here regarding the Outlook Client and Email Router etc. as they are not relevant on my project.

    That’s my plan at this stage.  I will come back and edit this blog as the project progresses.  If you have any experiences to share please post comments.

How to view Ribbon Definitions in CRM 2011

Previously the SDK contained ribbon definition XML files in a folder at the following location:


The latest SDK seems to no longer include these files.  So, now you need to generate these yourself using the utility provided.  It’s not hard to do, here’s the steps:

Go to this location:


Double-click the solution file (exportribbonxml.sln) to open this solution in Visual Studio.

Right-click on the Solution in Visual Studio and select Build:


Wait for that process to complete and make sure Visual Studio doesn’t report any errors.  If that all went ok you will now have an exe you can run, at the following location:


Double click on the exe (ExportRibbonXml.exe) and then provide the details asked of you:


And that should generate the ribbon definition files that you need:


Activity Feeds in Microsoft CRM 2011

My first impression of Activity Feeds was “why is my Wall full of events that I triggered – i.e. things that I already know about – what’s the point of that?”  And the post content didn’t read very well either.  Together this equated to lots of noise that deterred me from wanting to look at the wall.  Damn, I was hoping this would be a nice feature!

Since that first impression I’ve spent a bit more time with the feature and thanks to helpful posts like Richard’s one here I have a better understanding of how we can make it work for us.  I’ve ended up reaching the same conclusion as Richard: 

Activity Feeds can be of value, so long as you create your own posting rules via workflow and turn off the ones that are included out-of-the-box


Let me take you through it…

I created the following workflow to post to the Account wall every time a new Opportunity is created under the Account:



I then logged in as Gareth Tucker, went to the Account “Recreation Supplies (sample)” and clicked the Follow button on the Account’s Record Wall:


I then logged in as Rambo George and created an Opportunity under that Account:


I wait a few minutes for the workflow to run and then check the Account’s Record Wall and can see the Post:


Note: the post reads a lot better than those created by the out of the box rules supplied by Microsoft

Now, when I check Rambo George’s “What’s New” Wall I don’t see any Post:


This is correct, Rambo is not following the Account.  And this is GOOD Rambo does not need to be notified of something he has just done.

Now, I log back in as Gareth Tucker and remember Gareth is following this Account so he wants to know about this Opportunity.  The post appears there on Gareth’s “What’s New” wall:


So that’s activity feeds, a potentially useful self service feature for subscribing to CRM event notifications.

The one limitation I am still uncomfortable with though is the business benefit of Activity Feeds is reliant on end user’s choosing to view their wall.  Some people prefer email.  It’s a shame that when you follow you can’t chose to receive an email notification.  I think there’s an ISV opportunity here to develop maybe an email digest solution so that each day users receive an email from CRM with a consolidated post list.  Another nice solution would be to incorporate the Wall on a Dashboard to combine the news feed with rich data visualisations.  Then I think you have a compelling home page for end users too land on when they launch CRM.

Update 1: check out this post to see how you can easily embed the Activity Feed wall on a Dashboard.


Update 2: here’s an improved approach for writing your workflows that will add hyperlinks into your posts…

Instead of inserting primary attribute fields like Opportunity.Topic insert the new special Post URL(Dynamic) fields now available since Rollup 5.   These will give you the same text value but displayed as a hyperlink. 

Here’s how it looks in the Workflow designer:


And here’s how the resulting post looks:


Installing a 2-server CRM 2011 with Service Accounts and Minimum Permissions

Recently for a proof of concept I needed to supply a CRM installation installed to Microsoft’s best practices – i.e. a 2 server environment, SSL (HTTPS) and each service running under a separate service account.   Here are some notes on what was required to make this work.

If you miss some of these steps the common symptoms are:

  • Can only access CRM directly on the CRM server
  • CRM Reports don’t work
  • Outlook Client does not Configure
  • Authentication prompts appear as you try and access CRM

Environment: VirtualBox

  • Machine 1 = Domain Controller and SQL Server,
  • Machine 2 = CRM Server


  1. Install Windows Server 2008 R2 64-bit on both Machines, create C and D drive partitions (install all application software on the D drive)
  2. Promote Machine 1 to be a Domain Controller
  3. Create service accounts for SQL Server and SSRS
  4. Install SQL and SSRS on Machine 1
  5. Add Machine 2 to the domain
  6. Create an installer account:  crmadmin
  7. Create service accounts:  crmservice, crmdeploy, crmemail, crmasync, crmsandbox
  8. Grant minimum permissions per the CRM Implementation Guide’s instructions
  9. Logon as the installer account and install CRM Server on Machine 2
  10.   Test CRM access over HTTP via Internet Explorer on Machine 2
  11.   Install CRM SSRS Data Connector on Machine 1
  12.   Install latest rollup packs for CRM Server and SSRS Data Connector
  13.   Create a self signed certificate on Machine 2 (in IIS)
  14.   Go into CRM Deployment Manager, go to Servers, disable the CRM Server
  15.   Go to IIS and edit the Bindings for the CRM Web Site, enable HTTPS, disable HTTP
  16.   Back in CRM Deployment Manager, right-click on “Microsoft Dynamics CRM” and select Properties, then on the Web Address tab select HTTPS and enter the URLs
  17.   Re-enable the CRM server in Deployment Manager
  18.   Test CRM access over HTTPS via Internet Explorer on Machine 2
  19.   Create an SPN for the CRM service account (the identity running the CRM app pool)     (e.g. setspn –A HTTP/VBOXCRM gtdomain\crmservice) (command should always be HTTP even when HTTPS is enabled)
  20.   In Active Directory Users & Computer grant the Trust for Delegation permission to the CRM service account and the CRM server Computer Name (you need to do a Run As Administrator in order for the Delegation tab to appear when editing the properties of the Computer account)
  21.   Shutdown Machine 2, reboot Machine 1, restart Machine 2
  22.   Test CRM access over HTTPS via Internet Explorer on Machines 1 and 2
  23.   Test CRM Reports on Machines 1 and 2
  24.   Test the CRM Async Service by creating and triggering a simple workflow
  25.   Test the Deployment Service by creating a second CRM Organisation
  26.   Install the CRM Email Router and its Rollup Pack, configure and test
  27.   Machine 1, install Outlook, configure an email profile (perhaps connect to a Hotmail account) and then install the CRM Outlook Client and its Rollup Pack, configure and test

Done Smile


UPDATE 1: The configuration of the Outlook Client in the above HTTPS environment failed for us (“Could not establish trust relationship for the SSL/TLS secure channel“)  we think due to the use of the Self Signed Certificate.  Installing an Enterprise Certificate Authority and creating both a Root Certificate and a Certificate for the CRM Web site along with an additional SPN solved that problem for us (setspn –A HOST/VBOXCRM gtdomain\crmservice)

UPDATE 2: If you are not able to run Fetch XML reports or Report Wizard reports (which are Fetch XML reports) then you are likely suffering a firewall issue as described here.  Thanks to my colleague Farooq for finding this post and thanks Jim for writing it!