Skip to content
Daryl LaBar edited this page Apr 21, 2015 · 19 revisions

Welcome to the XrmToolBox wiki!

This wiki will help you to use XrmToolBox in the most efficient way! From connecting to a Microsoft Dynamics CRM deployment to developing your own plugin, everything is (or will be) here.

Hiring

I need help to create documentation for this project. I'm looking for help in the following domains:

  • Each plugin documentation
  • Custom plugin development

Using XrmToolBox

Development

  • Develop your own custom plugin for XrmToolBox!

Create a Project

First, create a new Visual Studio project of type library:

VS New Project - Library

Update Project Properties

Project properties are used to display your tool in the tools list. Title, Description and Company are used.

Project Assembly Properties

Add References

Add the following references to the project:

  • Microsoft.Crm.Sdk.Proxy
  • Microsoft.Xrm.Sdk
  • System.Drawning
  • System.Runtime.Serialization
  • System.ServiceModel
  • System.Windows.Forms
  • XrmToolBox (this tool executable)

References should look like the screenshot below:

Required References

Add a User Control

Add a new user control

Add a user Control This user control must implement the IMsCrmToolsPluginUserControl interface defined in the XrmToolBox executable. The easiest way to do this is to inherit from the XrmToolBox.PluginBase. The interface contains the following elements:

using System;
using System.Drawing;
using Microsoft.Xrm.Sdk;

namespace XrmToolBox
{
    public interface IMsCrmToolsPluginUserControl
    {    
        /// <summary>
        /// Gets the organization service used by the tool
        /// </summary>
        IOrganizationService Service { get; }

        /// <summary>
        /// Gets the logo to display in the tools list
        /// </summary>
        Image PluginLogo { get; }

        /// <summary>
        /// EventHandler to request a connection to an organization
        /// </summary>
        event EventHandler OnRequestConnection;

        /// <summary>
        /// EventHandler to close the current tool
        /// </summary>
        event EventHandler OnCloseTool;

        /// <summary>
        /// Method to allow plugin to Cancel a closing event, or perform any save events required before closing.
        /// </summary>
        void ClosingPlugin(PluginCloseInfo info);

        /// <summary>
        /// Updates the organization service used by the tool
        /// </summary>
        /// <param name="newService">Organization service</param>
        /// <param name="actionName">Action that requested a service update</param>
        /// <param name="parameter">Parameter passed when requesting a service update</param>
        void UpdateConnection(IOrganizationService newService, string actionName = "", object parameter = null);
    }
}

Implement the Interface on the User Control

You may choose to “roll your own”, but the simplest way to get started is to use the XrmToolBox.PluginBase. It fully implements the interface, and allows you to focus completely on your plug-in logic.

Plug-in Entry and Exit Methods

You can choose to trigger any specific plug-in logic however you like. In this tutorial, we’ll use a button, BtnWhoAmI to start the logic of the plug-in, and BtnClose to close the plug-in. Add these two buttons to your plug-in using the design window. After they are added double click them to generate the Click event handlers. Implement them as follows:

private void BtnWhoAmI_Click(object sender, EventArgs e)
{
    ExecuteMethod(ProcessWhoAmI);
}
 
private void BtnClose_Click(object sender, EventArgs e)
{
    base.CloseTool();
}

The CloseTool will call an event in the XrmToolBox that will then call the ClosingPlugin method (ClosingPlugin will get called anytime a plug-in has to close).

public virtual void ClosingPlugin(PluginCloseInfo info)
{
    if (info.FormReason != CloseReason.None ||
        info.ToolBoxReason == ToolBoxCloseReason.CloseAll ||
        info.ToolBoxReason == ToolBoxCloseReason.CloseAllExceptActive)
    {
        return;
    }

    info.Cancel = MessageBox.Show(@"Are you sure you want to close this tab?", @"Question", MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes;
}

Its uses the standard Windows Form Cancel Event to cancel the close by setting Cancel to true. The PluginBase by default will pop up a MessageBox with a standard, "Are you sure" message, whenever the user attempts to close a single plug-in. If the user selects to close multiple tabs, or closes the form itself, it won't prompt the user. If there are config settings that need to be saved in the plug-in, this method should be overriden, most likely calling any custom plug-in closing logic required, then calling base.ClosingPlugin.

The ExecuteMethod handles ensuring that the XrmToolBox has a valid open connection, before attempting to make an SDK call. If it doesn't have a valid connection, it will prompt the user to connect, and then call the method passed in, in this case ProcessWhoAmI.

Plug-in Logic

In order to simplify multithreading logic, the base provides a WorkAsync method with two different signatures. One provides the ability to perform multiple actions, and notify the user of the work that is being performed:

WorkAsync("Message To Display...",
    (w, e) => // Work To Do Asynchronously
    {
        w.ReportProgress(0, "Doing Something");
        //Do something
        w.ReportProgress(50, "Doing Something Else");
        //Do something else
 
        // Populate whatever the results that need to be returned to the Results Property
        e.Result = new object();
        w.ReportProgress(99, "Finishing");
    },
    e => // Finished Async Call.  Cleanup
    {
        // Handle e.Result
    },
    e => // Logic wants to display an update.  This gets called when ReportProgress Gets Called
    {
        SetWorkingMessage(e.UserState.ToString());
    }
);

The other, which we will use for this tutorial, assumes that one SDK call is being performed and and provides actions to perform the call, and process the result:

WorkAsync("Retrieving your user id...",
    (e) => // Work To Do Asynchronously
    {
        var request = new WhoAmIRequest();
        var response = (WhoAmIResponse)Service.Execute(request);
 
        e.Result = response.UserId;
    },
    e =>  // Cleanup when work has completed
    {
        MessageBox.Show(string.Format("You are {0}", (Guid)e.Result));
    }
);

It is very important to note that any time you access the Service property, your call hierarchy should always go through the ExecuteMethod, and WorkAsync method!

Optional – Add a Logo

By default the PluginBase will return null for the plug-in logo, which results in no logo being displayed. To add your own logo, first add an image to your project resources:

Project Properties –> Resources –> Add Resource –> Add Existing File, and select the image you’d like to use. The image must be square, with 80 pixels on each side.

Then override the PluginLogo Property to return your image:

/// <summary>
/// Gets the logo to display in the tools list
/// </summary>
public override Image PluginLogo
{
     get { return Resources.MyLogo; }
}

Final Complete Class

The final code for our sample tool is the following:

public partial class SampleTool : XrmToolBox.PluginBase
{
    private void ProcessWhoAmI()
    {
        WorkAsync("Retrieving your user id...",
            (e) => // Work To Do Asynchronously
            {
                var request = new WhoAmIRequest();
                var response = (WhoAmIResponse)Service.Execute(request);

                e.Result = response.UserId;
            },
            e =>  // Cleanup when work has completed
            {
                MessageBox.Show(string.Format("You are {0}", (Guid)e.Result));
            }
        );
    }

    #region Events

    private void BtnWhoAmI_Click(object sender, EventArgs e)
    {
        ExecuteMethod(ProcessWhoAmI);
    }

    private void BtnClose_Click(object sender, EventArgs e)
    {
        base.CloseTool();
    }

    #endregion Events
}

Use your tool

Finally, compile the project and move the resulting assembly into the same folder as the XrmToolBox executable