Showing posts with label tool. Show all posts
Showing posts with label tool. Show all posts

Friday, February 27, 2009

Creating a Birthday Contact List

Today we welcome our guest blogger CRM MVP Darren Liu from the Crowe Horwath company.

Have you ever been asked by someone to get a list of contacts having birthdays during a certain time period from CRM? If so what have you done to perform this task? Within the application, birthdays are tracked on Contact records as a single date (including year). This causes problems when searching for birthdays in a certain time period as the birth date is evaluated including the year. To illustrate, consider the following example:

· John Dole, 10/1/1980

· Adam Smith, 9/1/1970

· Mark Francis, 10/10/1960

Within CRM, searching for date is done by range. There is no easy way to identify from the above contacts all those having birthday in October as any range you choose will include the year. Wildcard functions on date fields are not a workable solution.

There are several solutions to this problem including JavaScript to parse birthday on the onChange event, a custom report or a plug-in. The desired functionality is to be able to search by birth month, birth day, and/or birth year, allowing the user to quickly identify all birthdays in a certain time period.

In this blog, I will show you how to use a pre plug-in to parse the birthday field into day, month and year. This way, the users will able to perform searches using Advanced Find. I have chosen the plug-in approach because it will help me parse the birthday field not only when the users update the birthday on the contact form but also when updating the birthday through the CRM web service for data imports and data integration.

Implement the pre plug-in

1. Create New Attributes

Create three new attribute on the Contact entity form in CRM. After creating the new attributes, publish the Contact customization.

Display Name

Schema Name

Type

Searchable

Values

Birth Month

new_birthmonth

Picklist

Yes

Jan = 1, Feb = 2, Mar = 3, Apr = 4, May = 5, Jun = 6, Jul = 7, Aug = 8, Sept = 9, Oct = 10, Nov = 11, Dec = 12

Birth Day

new_birthday

Int

Yes

Min Value = 1

Max Value = 31

Birth Year

new_birthyear

Int

Yes

Min Value = 1900

Max Value = 9999

clip_image002

2. Create pre plug-in using Visual Studio

Create a plug-in project name Crm.Plugin, copy and paste the following code to your Plug-in project.

using System;


using System.Collections.Generic;


using System.Text;


using Microsoft.Crm.Sdk;


using Microsoft.Crm.SdkTypeProxy;


 


namespace Crm.Plugin


{


  public class MonthDayYearContactPlugin : IPlugin


  {


    public void Execute(IPluginExecutionContext context)


    {


    DynamicEntity entity = null;


 


    if (context.InputParameters.Properties.Contains(ParameterName.Target) &&


        context.InputParameters.Properties[ParameterName.Target] is DynamicEntity)


    {


        entity = (DynamicEntity)context.InputParameters[ParameterName.Target];


        if (entity.Name != EntityName.contact.ToString()) { return; }


    }


    else


    {


        return;


    }


 


    try


    {


        if (entity.Properties.Contains("birthdate"))


        {


            CrmDateTime _birthdate = (CrmDateTime)entity["birthdate"];


            if (_birthdate.IsNull)


            {


                entity["new_birthday"] = CrmNumber.Null;


                entity["new_birthmonth"] = Picklist.Null;


                entity["new_birthyear"] = CrmNumber.Null;


            }


            else


            {


                DateTime birthdayValue = _birthdate.UserTime; 


                entity["new_birthday"] = new CrmNumber(birthdayValue.Day);


                entity["new_birthmonth"] = new Picklist(birthdayValue.Month);


                entity["new_birthyear"] = new CrmNumber(birthdayValue.Year);


            }


        }


    }


    catch (Exception ex)


    {


        throw new InvalidPluginExecutionException("An error occurred in the Month, Day, Year Plug-in for Contact.", ex);


    }


    }


  }


}


 




3. Register the plug-in The last step is to register the plug-in. To register the plug-in, you may use the Plug-in Registration tool from the MSDN Code Gallery. After the assembly is uploaded, you need to associate the following steps to the plug-in:





 
























Message: Create


Primary Entity: contact


Filtering Attributes: birthdate


Eventing Pipeline Stage of Execution: Pre Stage


Execution Mode: Synchronous



Triggering Pipeline: Parent Pipeline



Message: Update


Primary Entity: contact


Filtering Attribute: birthdate


Eventing Pipeline Stage of Execution: Pre Stage


Execution Mode: Synchronous



Triggering Pipeline: Parent Pipeline



Message: Create


Primary Entity: contact


Filtering Attributes: birthdate


Eventing Pipeline Stage of Execution: Pre Stage


Execution Mode: Synchronous



Triggering Pipeline: Child Pipeline



Message: Update


Primary Entity: contact


Filtering Attribute: birthdate


Eventing Pipeline Stage of Execution: Pre Stage


Execution Mode: Synchronous



Triggering Pipeline: Child Pipeline





Summary








That’s all there is to it! The users will now be able to use Advanced Find to quickly identify their contacts birthday in a certain time period from now on. For the existing contacts previously stored in CRM, you will need to write a one-time SQL script to update the birthday fields in the MSCRM database in order for CRM to return the correct data back to the users. Hopefully this will help you on your next CRM project.



clip_image004



clip_image006



Cheers,



Darren Liu



Published Friday, February 27, 2009 9:26 AM by crmblog

Round Robin Lead Assignment

Mitch Milam's Microsoft Discussions



If you use Microsoft Dynamics CRM and have a sales staff of more than one person, then you have probably encountered to need to assign incoming sales leads equally among your sales staff.

The Round Robin Lead Assignment solution was created to automatically assign new sales leads to a team of sales people in a round-robin fashion.

Features

Utilizes the built-in features of Dynamics CRM 4.0

Through the use of Teams and a custom workflow, you can determine how leads are assigned to your sales teams.

Support for an unlimited number of sales teams

Round-Robin can assign leads to an unlimited number of sales teams, depending on how your sales organization is structured.

Virtually maintenance free.

Once Round-Robin has been installed and configured, the only ongoing maintenance required is for you to maintain the members of the Team (or Teams).

How It Works

For this discussion, we’ll use the South Central Sales District Team that contains four members, as shown in the figure below:

image

Using the Round-Robin method of assigning new sales Leads, Jose Curry will be the first person to receive a lead. The next Lead would be assigned to Gail, then Alan, then Connie. When the fifth new sales lead arrives, Round-Robin understands that Connie is the last person in the list and will start the Lead assignment process at the beginning with Jose and proceed down the list again.

Pricing

$125.00USD per CRM Organization.   Click here to order.

Thursday, February 12, 2009

ISV Utilities for Comparing Customizations and Transferring Configuration Data

Yippie. These tools will help compare two systems and see where the changes are.

 

Inna Agranov
Microsoft Corporation

February 2009

Summary

Learn how to build and use two new powerful tools developed for Microsoft Dynamics CRM. The Customization Comparison Utility lets you compare the customization files between two Microsoft Dynamics CRM systems and the Configuration Data Utility lets you transfer custom configuration data from one Microsoft Dynamics CRM system to another.

Download the Visual Studio 2008 and Visual C# code samples for this article:

The Readme.doc documents that are included with the sample code contain information about how to set up and build the sample applications. The user guides contain detailed information about how to use the sample applications and view the results.

Applies To

Microsoft Dynamics CRM 4.0

Microsoft Visual Studio 2008

Introduction

Microsoft Dynamics CRM is a highly customizable system. Not only you can modify different sections of the product, you can also create new components to address business needs. The Microsoft Dynamics CRM platform offers a robust set of tools, APIs, and documentation that helps you build custom business applications. As the applications built on the Microsoft Dynamics CRM platform become more and more complex, a need for specialized support tools grows. In this article you will learn about two very useful tools that help you analyze the impact of customizations on the system and maintain consistent configuration data across multiple Microsoft Dynamics CRM systems.

Evaluating the Impact of Customizations with the Customization Comparison Utility

To evaluate the impact of customizations, it is helpful to compare customization files between the source and the target systems before you import customizations. The Customization Comparison Utility helps you accomplish this task.

Analyzing Customizations

Often you have to export custom components from one Microsoft Dynamics CRM environment and import them into another, for example, from development into test or production. However, before you import customizations, it is very helpful to assess the impact of customizations on the target system. The system where you import customizations may have been changed since the last installation. You have to consider the extent of the changes and how they may affect the new installation. While some of the changes, such as renaming of the attributes or adding new attributes, are minor, other modifications, such as deletion of entities or changes in the forms may have a significant effect on the system.

Analyzing and understanding the system customizations may result in more successful deployment of a new version of the application. This analysis minimizes the risk of overwriting important customization data in the target system. For example, if only several attribute names have changed, you may be able to do a plain import using the import/export functionality built into Microsoft Dynamics CRM. However, if some key components were deleted, such as entity forms, you may have to merge the customizations with the changes in the target system. Comparing customization files between the two systems helps you determine which approach will result in more successful deployment. This is also very useful when you are diagnosing the problems between two systems. By comparing the customization files, you can often identify possible causes of the existing problems.

Using the Customization Comparison Utility

The Customization Comparison utility lets you easily compare two Microsoft Dynamics CRM customization.xml files. Unlike other XML comparison tools, this utility can read and understand Microsoft Dynamics CRM schema. The results of comparison show the differences in entities, attributes, forms, views, workflows, security roles, entity maps, and relationships. You can use this tool before you import customizations into a system to evaluate the effect they will have on the system.

Use the tool to compare XML customizations files between the source and the target systems. If you use a zipped customization file, make sure that it contains only one customization XML file. The following illustration shows the results of comparison between two customization files. The compared items include entities, roles, workflows, entity maps, and relationships. You can drill down into each item to see more details. From the entities, you can view the changes in attributes, forms, and system views. You can easily see the changes in source and target. It shows the items that are present in the source file and not present in the target file and the items that are present in the target file, but not in the source file.

Dd442453.a7338331-120b-4f29-ab17-1c94b85e014b(en-us,MSDN.10).gif

In addition to reviewing the results of the comparison in the grid, the tool includes a report that you can easily export to Microsoft Office Excel for additional analysis.

The tool offers a command line version that you can run from a command prompt.

For more information about how to use the tool, see the Customization Comparison user's guide included in the download package for this utility.

Transferring Configuration Data with the Configuration Data Utility

When you work with multiple environments, such as development, test, and production, or multiple Microsoft Dynamics CRM organizations, keeping consistent configuration data across all systems can be very important. The Configuration Data Utility helps you achieve this. It lets you export custom configuration data from a source Microsoft Dynamics CRM system and import it to a target Microsoft Dynamics CRM system.

Storing Configuration Data in Custom Entities

In Microsoft Dynamics CRM you often use custom entities to store business information. However, you could also use custom entities to store system configuration data. For example, if an application integrates Microsoft Dynamics CRM with a third-party system, you could create a configuration entity with attributes such as pollingtime, url, and retries to store the configuration data needed for the integration. This is very convenient because the data stored in the configuration entity can be used by the system administrators to configure a new application or update an existing application. To keep the configuration data up to date, you may have to frequently upload the new data, or have an automated task to do it.

Using the Configuration Data Utility gives you a simple and efficient way to transfer custom configuration data from one system to another. One of the main benefits of this utility is that you can import configuration data from multiple custom entities at the same time. While it only imports and exports data for custom entities, the tool can handle useful scenarios, such as importing records that reference other records that are also being imported.

Dd442453.Important(en-us,MSDN.10).gifImportant

For the tool to work correctly, the schema for the source entities and the target entities must be identical.

Dd442453.note(en-us,MSDN.10).gifNote

In more complex cases, use the Microsoft Dynamics CRM data export and import tools or Data Migration Manager to transfer data for custom and system entities.
For more information about these tools, see Microsoft Dynamics CRM online Help.

Using the Configuration Data Utility

Use the Configuration Data Utility to export the source system configuration data and import it into a target system. The tool provides a convenient interface that lets you select the custom entities that contain the configuration data in the source system, save the data into a data file, and then import the records from the data file into a target system.

To run the tool, you must be a system administrator with appropriate privileges to create, read, and update entity instances.

The following illustration shows the entities in the source system that are selected for export.

Dd442453.0b8f0a81-1a17-4d77-9419-1cdc12427223(en-us,MSDN.10).gif

For import, specify the target server where you import the configuration data and the data file that you created during export, as shown in following illustrations.

Dd442453.9436a94c-f84f-4151-8d85-edc09ecaa422(en-us,MSDN.10).gif

Dd442453.5841695f-63ff-4ebb-a3b4-143657a9f759(en-us,MSDN.10).gif

For more information about how to use the tool, see the Configuration Data Utility user's guide included in the download package for this utility.

Report Scheduler Tool

Jonw wrote this on his blog


I created a tool using Visual Studio and the CRM web services that can execute a saved query and then email the results as a CSV file. I've presented in a video at www.democrmonline.com/reportscheduler.

There is also sample code at Report Scheduler Sample Code.

With a small change, this tool could be used with the Windows scheduler to run automatically. I left this out intentionally since this code is NOT supported and is as is.

At the least, it's quick start if you wanted to build your own.

-cheers
Jonw

Tuesday, August 5, 2008

CRM 4.0 E-Mail Connector Logger Tool

Published Wednesday, July 02, 2008 2:19 PM by benlec

Hi all,

 

I’ve just made this tool to easily enable logging for the E-Mail Connector in CRM 4.0

The logging for the connector can be enabled by modifying the configuration file for the service like explained in this article:

 

http://blogs.msdn.com/benlec/archive/2008/03/25/how-to-implement-logging-for-the-microsoft-crm-4-0-e-mail-connector.aspx

 

The tool looks like this:

 

CRM 4.0 E-Mail Connector Logger GUI

 

It’s based on XPath to read and modify the Config File.

 

Here is how it works:

1°) Execute the tool on the E-Mail Connector box, it will detect and read the config file.

2°) The drop down list you see shows you the Deployment you have configured, you need to select one of these.

3°) Once the deployment is selected, it will retrieve the different profiles you configured (Incoming Users & Queues, Forward Mailbox and Outgoing profile)

4°) You can select the section you want to activate logging for. If you need to only activate logging for Incoming E-Mail on Peter Chimaera, then select the 1st Checkbox only and select Peter from the Drop down.

5°) Choose a FileName (there will be a default filename proposed) and a LogLevel.

6°) Click [Enable Logging]

 

Important Notes:

- Don’t close the tool once you enabled logging. It will STOP the logging. (it has some dialog box which reminds you the usage anyways)

- One you are done with your tests, click [Stop Logging]

- The log files will be placed in the SAME folder as the Microsoft.Crm.Tool.EmailAgent.xml file

- There will be no update of the Configuration during the test (if in the meantime a new user is configured, it will not take it in consideration) because once you click [Enable Logging] the tool will set the ConfigUpdatePeriod to ZERO to prevent any unexpected update during the test (to prevent cancelling logging).

 

Risks:

- There should be no risks to do this because the tool automatically Create a backup of the EmailAgentXML when we attempt to Enable Logging.

If an unexpected error occurs, the backup will be restored. The backup is restored also if you exit the application….

- You can run it if the EmailAgentXML has already been modified because it will check if the LogLevel and LogFile tag exists already or not and will either modify or create the tags accordingly.


Regards

Benjamin

It's the little things! JavaScript Extraction Tool

I just saw this post by Joris Kalz on his blog posted Monday, August 04, 2008 5:04 PM and I cannot wait to try it out. There has been many times I wanted a tool like this, plus it will help me document those hidden customizations for my clients. WAY TO GO Joris and thanks.


I recently had to transfer several customizations to a different CRM installation. While Microsoft Dynamics CRM offers an export and import functionality, in this case I just wanted to select specific client side customizations. However, manually grabbing all jscript code is a little bit time consuming. Instead, I wrote a few lines of code to export all jscript code without annoying interaction.VS Project CRM to JS Export

 

The code is pretty straight forward, so feel free to modify. You can download the VS 2008 project here: Microsoft Dynamics CRM Jscript Export Tool

Before you start this tool, you have to change the app.config according to your CRM installation:

WindowClipping

After running the tool, all client side jscript will be stored at the declared output folder.Running-CRM-Jscript-Export-Tool

The result will be a list of all entities containing jscript separated by event type and further by form and field events.

JScript-File-List

Hopefully you like this tool. In the final stage of this tool, it will be even possible to write changes back to Microsoft Dynamics CRM.

Tuesday, July 22, 2008

The Stunnware Tools Framework for Microsoft Dynamics CRM 4.0 - Professional Edition

STUNNWARE Tool is a must for CRM Developers!

As previously announced there will be a professional edition of the Stunnware Tools for Microsoft Dynamics CRM 4.0. It's almost complete, besides the documentation, but I wanted to show you some of the features you can expect when going for the professional edition.

I'm starting with the query builder, formerly known as the FetchXml wizard. What you have so far is the following:

  1. Create a query using a visual designer
  2. Paste an existing query, parse it and edit in the designer window
  3. Analyze the query and create .NET code executing the same query with a QueryExpression. Available for C# and VB.NET

The professional edition adds the following new features:

  1. Create .NET code for any available .NET language. Though C# and VB.NET are the most common ones, you can also create code for C++, J# or whatever you prefer.
  2. Execute the .NET code and run the query. It allows you to make changes and test before using the code in your own applications.
  3. Tracking the SOAP messages being sent and received. If you add additional .NET code, like Create, Update or Delete statements, you will get a list of all SOAP messages.
  4. Creates the JavaScript code you need in your CRM forms to access the CRM service. Again, the code is available for each request you made.

The video

I think it's easier to show the application than talking about it, so here's a short video created with Jing (awesome tool). It requires the Adobe Shockwave Player to be installed on your machine though.

 

Wednesday, July 16, 2008

Creating A Debugger Visualizer For Dynamic Entities

Simon Hutson wrote this on Tuesday, July 08, 2008 9:12 PM


Are You Gonna Be My Girl....


Over the last couple of months I've been spending quite a bit of time with the SDK, building custom workflow activities and plug-ins for CRM 4.0. One of the problems working with the IPlugin interface is that you are forced to use the DynamicEntity class when accessing the InputParameters and OutputParameters properties of the plug-in context.


This wouldn't be so bad, except that it is a real pain trying to find out what properties and values are actually contained within a Dynamic Entity whilst debugging and so I kept having to write the same "test harness" code over and over again just to examine their contents. However, last week I found out you can actually extend Visual Studio to provide this support by implementing a custom debugger visualizer.


Custom debugger visualizers were introduced in Visual Studio 2005 and enable you to view the contents of an object or variable in a meaningful way whilst debugging your application. Out of the box, Visual Studio ships with four standard visualizers, including the "Text Visualizer", "HTML Visualizer", and "XML Visualizer", all of which work on string objects, and the "DataSet Visualizer", which works for DataSet, DataView, and DataTable objects. However, none of these understand the how to work with the complexities of DynamicEntity object.


Fortunately there is plenty of information available online (how to write a visualizer, Creating Debugger Visualizers with Visual Studio 2005), and even a good Channel9 video interview with the Visual Studio program manager responsible for this feature - Scott Nonnenberg - Visualizers in VS 2005. This is well worth watching if you want to really understand how you can improve your debugging experience.


After playing around with this for a few hours I came up with a really cool solution using a TreeView and DataGridView control to provide detailed drill-down into dynamic entities. As you can see below, whenever the Visual Studio comes across an object of type Microsoft.Crm.Sdk.DynamicEntity, the visualizer is represented in the debugger by a magnifying glass icon. When you see the magnifying glass in a DataTip, in a debugger variables window or in the QuickWatch dialog box, you can click on the magnifying glass to select the DynamicEntity Visualizer.


Calling The DynamicEntity Visualizer


Once launched, the DynamicEntity Visualizer iterates through all the dynamic entity properties to build a tree view on the left side of the form, showing the property name and the property type. Clicking on each property, displays the property attributes in a table on the right side of the form.


Using The DynamicEntity Visualizer


At a basic level, a custom debugger visualizer is just a Windows Forms application that is launched by Visual Studio, with the object being debugged passed as a parameter.


The basic code you need to implement the visualizer is shown below. You will need to get a reference to "Microsoft.VisualStudio.DebuggerVisualizer.dll" which ships with Visual Studio, but you do need to make sure you are using the correct version of this assembly depending on whether you are using Visual Studio 2005 or Visual Studio 2008.



Imports System.ComponentModel
Imports System.Windows.Forms
Imports Microsoft.VisualStudio.DebuggerVisualizers
Imports Microsoft.Crm.Sdk
 
<Assembly: DebuggerVisualizer(GetType(DynamicEntityVisualizer), GetType(VisualizerObjectSource), Target:=GetType(Microsoft.Crm.Sdk.DynamicEntity), Description:="DynamicEntity Visualizer")> 
 
Public Class DynamicEntityVisualizer
    Inherits DialogDebuggerVisualizer
 
    Protected Overrides Sub Show(ByVal windowService As IDialogVisualizerService, ByVal objectProvider As IVisualizerObjectProvider)
 
        Dim de As DynamicEntity = CType(objectProvider.GetObject, DynamicEntity)
 
        ' Process dynamic entity and display windows form here
 
    End Sub
 
End Class

The <Assembly> attribute is used by Visual Studio to associate the Microsoft.Crm.Sdk.DynamicEntity type with the Visualizer, and once compiled, you can simply copy your assembly to the folder "C:\Program Files\Microsoft Visual Studio 9.0\Common7\Packages\Debugger\Visualizers\". Visual Studio will automatically use any visualizers it finds in this folder.


To build the user interface, simply create a new Windows Form in the project, add a "SplitContainer" control and place a "TreeView" control on the left side of the split and a "DataGridView" control on the right.


Next, create a "DynamicEntityProperty" class that we can use to store property attribute names and values.



Friend Class DynamicEntityProperty
 
    Private _propertyName As String
    Public Property PropertyName() As String
        Get
            Return _propertyName
        End Get
        Set(ByVal value As String)
            _propertyName = value
        End Set
    End Property
 
    Private _propertyValue As String
    Public Property PropertyValue() As String
        Get
            Return _propertyValue
        End Get
        Set(ByVal value As String)
            _propertyValue = value
        End Set
    End Property
 
    Public Sub New(ByVal name As String, ByVal value As String)
        _propertyName = name
        _propertyValue = value
    End Sub
 
End Class

Next we have to implement the logic that iterates through the dynamic entity and populates the "TreeView" control as shown below.



Private Function AddDynamicEntityToTreeNode(ByVal node As TreeNode, ByVal entity As DynamicEntity) As TreeNode
 
    For Each [property] In entity.Properties
        Dim childNode As New TreeNode([property].Name + " (" + [property].GetType.Name + ")")
        If TypeOf [property] Is DynamicEntityArrayProperty Then
            For Each childEntity In CType([property], DynamicEntityArrayProperty).Value
                childNode = AddDynamicEntityToTreeNode(childNode, childEntity)
            Next
        Else
            childNode = AddDynamicEntityPropertyToTreeNode(childNode, [property])
        End If
        node.Nodes.Add(childNode)
    Next
 
    Return node
 
End Function

Once we have a "TreeView" with one or more "TreeNode" objects, we have to implement the logic that iterates through the attributes for each individual property, and add them to the TreeNode.Tag property as shown below. To keep the code short, and avoid writing the same For...Next code for each CRM property type, I decided to make use of .NET Reflection within the "AddDynamicEntityPropertyValueToTreeNode" function.



Private Function AddDynamicEntityPropertyToTreeNode(ByVal node As TreeNode, ByVal [property] As [Property]) As TreeNode
 
    If TypeOf [property] Is CrmBooleanProperty Then
        Dim p = CType([property], CrmBooleanProperty)
        Dim value = CType(p.Value, CrmBoolean)
        node = AddDynamicEntityPropertyValueToTreeNode(node, value)
    ElseIf TypeOf [property] Is CrmDateTimeProperty Then
        Dim p = CType([property], CrmDateTimeProperty)
        Dim value = CType(p.Value, CrmDateTime)
        node = AddDynamicEntityPropertyValueToTreeNode(node, value)
    ElseIf TypeOf [property] Is CrmDecimalProperty Then
        Dim p = CType([property], CrmDecimalProperty)
        Dim value = CType(p.Value, CrmDecimal)
        node = AddDynamicEntityPropertyValueToTreeNode(node, value)
    ElseIf TypeOf [property] Is CrmFloatProperty Then
        Dim p = CType([property], CrmFloatProperty)
        Dim value = CType(p.Value, CrmFloat)
        node = AddDynamicEntityPropertyValueToTreeNode(node, value)
    ElseIf TypeOf [property] Is CrmMoneyProperty Then
        Dim p = CType([property], CrmMoneyProperty)
        Dim value = CType(p.Value, CrmMoney)
        node = AddDynamicEntityPropertyValueToTreeNode(node, value)
    ElseIf TypeOf [property] Is CrmNumberProperty Then
        Dim p = CType([property], CrmNumberProperty)
        Dim value = CType(p.Value, CrmNumber)
        node = AddDynamicEntityPropertyValueToTreeNode(node, value)
    ElseIf TypeOf [property] Is CustomerProperty Then
        Dim p = CType([property], CustomerProperty)
        Dim value = CType(p.Value, Customer)
        node = AddDynamicEntityPropertyValueToTreeNode(node, value)
    ElseIf TypeOf [property] Is EntityNameReferenceProperty Then
        Dim p = CType([property], EntityNameReferenceProperty)
        Dim value = CType(p.Value, EntityNameReference)
        node = AddDynamicEntityPropertyValueToTreeNode(node, value)
    ElseIf TypeOf [property] Is KeyProperty Then
        Dim p = CType([property], KeyProperty)
        Dim value = CType(p.Value, Key)
        node = AddDynamicEntityPropertyValueToTreeNode(node, value)
    ElseIf TypeOf [property] Is LookupProperty Then
        Dim p = CType([property], LookupProperty)
        Dim value = CType(p.Value, Lookup)
        node = AddDynamicEntityPropertyValueToTreeNode(node, value)
    ElseIf TypeOf [property] Is OwnerProperty Then
        Dim p = CType([property], OwnerProperty)
        Dim value = CType(p.Value, Owner)
        node = AddDynamicEntityPropertyValueToTreeNode(node, value)
    ElseIf TypeOf [property] Is PicklistProperty Then
        Dim p = CType([property], PicklistProperty)
        Dim value = CType(p.Value, Picklist)
        node = AddDynamicEntityPropertyValueToTreeNode(node, value)
    ElseIf TypeOf [property] Is StateProperty Then
        Dim p = CType([property], StateProperty)
        Dim value = CType(p.Value, String)
        node = AddDynamicEntityPropertyValueToTreeNode(node, value)
    ElseIf TypeOf [property] Is StatusProperty Then
        Dim p = CType([property], StatusProperty)
        Dim value = CType(p.Value, Status)
        node = AddDynamicEntityPropertyValueToTreeNode(node, value)
    ElseIf TypeOf [property] Is StringProperty Then
        Dim p = CType([property], StringProperty)
        Dim value = CType(p.Value, String)
        node = AddDynamicEntityPropertyValueToTreeNode(node, value)
    ElseIf TypeOf [property] Is UniqueIdentifierProperty Then
        Dim p = CType([property], UniqueIdentifierProperty)
        Dim value = CType(p.Value, UniqueIdentifier)
        node = AddDynamicEntityPropertyValueToTreeNode(node, value)
    Else
        Throw New ArgumentException("Property type is not supported.", "property")
    End If
 
    Return node
 
End Function
 
Private Function AddDynamicEntityPropertyValueToTreeNode(ByVal node As TreeNode, ByVal value As Object) As TreeNode
 
    ' Create a list of DynamicEntityProperty
    Dim values As New BindingList(Of DynamicEntityProperty)
 
    ' Check this is not a string or a value type (i.e. this is a reference type)
    If Not (TypeOf value Is String) And Not (Type.GetType(value.GetType.AssemblyQualifiedName).IsValueType) Then
        ' Use reflection to get the public instance properties and their values from each property of DynamicEntity.value
        For Each propertyInfo In Type.GetType(value.GetType.AssemblyQualifiedName).GetProperties(Reflection.BindingFlags.Public Or Reflection.BindingFlags.Instance)
            ' Check that the property can be read.
            If propertyInfo.CanRead Then
                Try
                    values.Add(New DynamicEntityProperty(propertyInfo.Name, GetString(propertyInfo.GetValue(value, Nothing))))
                Catch ex As Exception
                    ' An unknown error occured, so ignore it and do nothing
                End Try
            End If
        Next
    Else
        values.Add(New DynamicEntityProperty("Value", value.ToString))
    End If
 
    ' Add the list to the TreeNode.Tag property
    node.Tag = values
 
    Return node
 
End Function
 
Private Function GetString(ByVal value As Object) As String
 
    If value Is Nothing Then
        Return String.Empty
    Else
        If TypeOf value Is Guid Then
            Return CType(value, Guid).ToString
        ElseIf TypeOf value Is Boolean Then
            Return value.ToString
        ElseIf TypeOf value Is Integer Then
            Return value.ToString
        ElseIf TypeOf value Is Date Then
            Return value.ToString
        ElseIf TypeOf value Is String Then
            Return value.ToString
        Else
            Return String.Empty
        End If
    End If
 
End Function

Finally, the last piece of code is needed to update the "DataGridView" by binding data stored in the "TreeNode.Tag" property when selecting a Dynamic Entity property in the "TreeView". We can also take this opportunity to set some properties on the "DataGridView" in order to make the table format look nice.



Imports System.Windows.Forms
Imports System.ComponentModel
 
Public Class DynamicEntityVisualizerForm
 
    Private Sub DynamicEntityTreeView_AfterSelect(ByVal sender As Object, ByVal e As System.Windows.Forms.TreeViewEventArgs) Handles DynamicEntityTreeView.AfterSelect
 
        PropertyDataGridView.DataSource = Nothing
 
        If Not (e.Node.Tag Is Nothing) Then
            PropertyDataGridView.DataSource = CType(e.Node.Tag, BindingList(Of DynamicEntityProperty))
            PropertyDataGridView.Columns.Item(0).AutoSizeMode = DataGridViewAutoSizeColumnMode.None
            PropertyDataGridView.Columns.Item(0).MinimumWidth = 100
            PropertyDataGridView.Columns.Item(0).Name = "Property Name"
            PropertyDataGridView.Columns.Item(1).AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill
            PropertyDataGridView.Columns.Item(1).MinimumWidth = 100
            PropertyDataGridView.Columns.Item(1).Name = "Property Value"
            PropertyDataGridView.ClearSelection()
        End If
 
    End Sub
 
    Private Sub DynamicEntityVisualizerForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
 
        PropertyDataGridView.Enabled = True
        PropertyDataGridView.SelectionMode = DataGridViewSelectionMode.CellSelect
        PropertyDataGridView.ClipboardCopyMode = DataGridViewClipboardCopyMode.EnableWithoutHeaderText
        PropertyDataGridView.RowHeadersVisible = False
        PropertyDataGridView.RowsDefaultCellStyle.WrapMode = DataGridViewTriState.True
        PropertyDataGridView.RowsDefaultCellStyle.Alignment = DataGridViewContentAlignment.TopLeft
        PropertyDataGridView.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCellsExceptHeaders
 
    End Sub
 
End Class

So there we have it. A really useful piece of functionality that saves time and effort when debugging your plug-ins and custom workflow assemblies. I built this solution in Visual Studio 2008, for debugging in Visual Studio 2008 and you can download the project files here.


If you want to use this "AS IS" you can just copy file "SRH.CRM.VisualStudio.DebuggerVisualizer.dll" from the \bin\debug project folder to the folder "C:\Program Files\Microsoft Visual Studio 9.0\Common7\Packages\Debugger\Visualizers\". However, if you do wish to modify the functionality, or re-compile it to run under Visual Studio 2005, then please feel free to do so.


This posting is provided "AS IS" with no warranties, and confers no rights.


Laughing Boy