Tag Archives: MSDYNCRM

Source code recovery tip: Was this written in c# or VB.NET?

Every now and again I run into the unfortunate circumstance where someone has lost the source code to a Dynamics CRM plugin (or something similar).

When you encounter this type of situation your only hope is to decompile the source using the plugin assembly’s DLL file and spend a good deal of time modifying the source code to get close to what the original author wrote.

Today my tool of choice is JustDecompile from the fine folks at Telerik.

Decompilation is not an exact science simply because the code the compiler ended up generating is not exactly like the code the author wrote. Most of the time this is caused by optimizations that the compiler has inserted which replace the original author’s code with code that it thinks is “better” or in some cases, just because.

So when reviewing a decompilation, it is sometimes hard to make a determination if what you see is compiler-generated or user-generated, especially when it is not your code. And I should note that I have seen a lot of code written by people whose main job was not that of a developer, who grabbed some code out of the Dynamics CRM SDK or off of the Internet to solve a problem, without really knowing what they were doing.

So when you look at the decompiled code, you are always asking: did they write it this way, or is this the way it was compiled?

Today I ran into something quite different.

First off, the using statements look very strange:

image

And some of the comparison operations used methods that I had never seen before:

image

Which is in the Microsoft.VisualBasic.CompilerServices namespace. 

Very odd.  Why would a developer writing C# use Visual Basic.NET assemblies?

The answer is: They would not.  This code was originally written in VB.NET, not C#.

So I am still going to use the C# decompilation code, but knowing that this was originally written in VB.NET helps me understand a little bit better some of the code that I am seeing.

Just another note to put into your book somewhere.

Dynamics CRM Upgrade Blocker: Orphan Plugin Step Image records

Last week I was working with another Microsoft partner who was upgrading a customer’s Dynamics CRM from 2011 to 2015 when they ran into the following error moving to Dynamics CRM 2013 (which you must do, to get to 2015):

image

Note: SdkMessageProcessingStep is the internal name for a plugin step, as configured using the Plugin Registration Tool.

So we ran the following script to see if we could not locate the offending SDK Message Processing Step.

SELECT 
 SdkMessageIdName,
 Name,
 EventHandlerName,
 SdkMessageProcessingStepId
FROM
 SdkMessageProcessingStep
WHERE
 SdkMessageProcessingStepId = 'd987ac98-8b85-dd11-b48e-001143ec27a2'

And we got nothing.

This is very strange so I started looking around for anything else that could cause such and error – and I actually found it.

Root Cause

The issue was actually on a separate tabled called: SdkMessageProcessingStepImage, which stores the Pre or Post Image configuration for a specific plugin step.

This CRM system was originally v4.0 and somewhere in the upgrade to CRM 2011 a plugin step was removed from the system and the Plugin Registration Tool did not remove the associated Plugin Step Image, so these records remained in the database, unused and unnoticed until the upgrade process tried to modify them.

The actual error message is displayed because the SdkMessageProcessingStepImage is referencing the SdkMessageProcessingStep, which doesn’t exist-just like the error says.

Correcting the Issue

To verify this is indeed the problem, we ran this script:

SELECT 
  *
FROM
  SdkMessageProcessingStepImage 

WHERE
 SdkMessageProcessingStepId = 'd987ac98-8b85-dd11-b48e-001143ec27a2'

This will produce records if you actually have orphan Plugin Step Images.

Your next step is to remove those records from the database using a SQL command.  Kind of scary, but they are not being used anyway.

Conclusion

I have seen this type of error message a number of times so it does happen occasionally, but not all that frequently.  My theory is that a specific version of the Plugin Registration Tool, probably for CRM 4.0, was responsible for this issue and it was correctly in later versions of the tool.

I think that I need to add this as an upgrade check to my SnapShot! documentation tool.

Manually Repairing a Sitemap. Part 1

As I mentioned a couple of week ago, my upgrade from CRM 2013 to CRM 2015 did not go well. One of the issues is my SiteMap was totally broken and I had to replace it with the “default.”

The only problem was I wiped out the custom entries for my marketing package, Click Dimensions.

No problem, I thought, I’ll just add the solution back.  Except that did not work.  I ran into ghost SiteMap entries from a previously remove solution. This required a call to Microsoft Support to get them corrected.

Once corrected, I was successfully able to import the solution.  Except there were no custom SiteMap entries.

Only only solution in this case is to manually add them, which involves this process:

The Process

1. Create a new solution.

2. Add the SiteMap to the solution.

3. Export the solution as unmanaged.

4. Unzip the solution files.

5. Take the solution file from the package you are attempting to import and unzip it as well.

6. Open the customization.xml file from step 4 in an editor like Visual Studio or Notepad++.

7. Open the customization.xml file from step 5 in an editor like Visual Studio or Notepad++.

8. Copy the information from the step 7 SiteMap and paste it into the proper location within the step 6 SiteMap.

9. You will need to remove some XML attributes that are specific to the Solution Import process. Here is an example:

<Group Id="Extensions" ResourceId="Group_Extensions" ordinalvalue="5" solutionaction="Added" />

You need to remove the any reference to ordianvalue and solutionaction.

10. Save the step 6 customization.xml file.

11. Re-Zip the files from step 4.

12. Import the solution back into CRM.

13. Refresh your browser and see if the SiteMap changes worked.

Things to Know

I did not get into great detail about the SiteMap itself because you really have to understand how it is organized and all of the components that are involved. If you do not understand these things, you can damage the SiteMap and render your CRM system inaccessible.

Before you start anything like this, please know and understand what you are doing.  See the references below.

If all else fails, open a case with Microsoft.

References

Edit the site map

SiteMap XML reference

SnapShot! 3.7 for Dynamics CRM is Available

My Dynamics CRM documentation tool, SnapShot!, version 3.7 is now available.

This version includes the following enhancements and corrections:

  • Compatibility with Dynamics CRM 2015 Online Update 1
  • The Entity and Field reports now have the GUID for each which I have found very useful when troubleshooting solution import issues.
  • Organizations with a large amount of customization are now better handled and will not encounter issues when exporting entities with large numbers of fields.
  • Issues encountered (randomly) when working with Dynamics CRM organizations that where previously created using Dynamics CRM 4.0 or before, have been corrected.

Visit the SnapShot! product page for more information.

Dynamics CRM 2015 Spring: Delete Plug-in Trace Log Records

So I am digging around the Dynamics CRM 2015 Spring Update, as I am apt to do, when I ran across something that needs to be changed.

There is a recurring bulk delete job that automatically deletes any plug-in trace log records older than one day, as you can see below:

image

This is a little too quick for my taste, so I would advise changing this value to be something longer, like seven or thirty days.

The real issue is that we cannot change the query used to select the jobs, but we can change the recurrence pattern.

Modifying a Recurring Job

To change a recurring job, perform the following steps:

1. Navigate to Settings, Data Management, Bulk Record Deletion.

2. Change your view to be: Recurring Bulk Deletion System Jobs

3. Open the bulk delete job in question.

4. Click the Actions button, the select Modify Recurrence. You will see the following dialog:

image

5. Change he following settings:

  • Run the job after every X days
  • Start time

Choose values that fit your organization.

6. Click the OK button.

That should change the recurrence so that the interval between runs is longer.

Beacon Idea #5: Retail, Analysis, and Dynamics CRM

So if you have been reading my blog frequently over the past few months you will notice that I have been doing  lot of mobile-related development, mostly with the Xamarin platform (which I absolutely love, btw).

One of the projects that I’m working on will involve the use of beacon, or iBeacon, technology.  I thought I would spend a little time today discussing how you can unite beacons and Dynamics CRM to collect a variety of information about your prospects and customers.

A Bit about Beacons

iBeacon is Apple’s technology for indoor positioning, where you need a finer-grained position that can be achieved using GPS. Apple decided to make the iBeacon specification available to other vendors and companies like Qualcomm and Estimote have products that are iBeacon compatible.

There are alternative beacon technologies available that are not iBeacon compatible, so for the sake of simplicity, I’ll just refer to everything as a “beacon” to keep things generalized.

Beacons are just transmitters that broadcast their position using Bluetooth Low Entergy, or BLE.

The intelligence dealing with where the beacons are located and their distance from the receiver, must be handled within an application that has connected to a mobile device’s BLE signal.

Currently, late models of iPhone, Android, and even some Windows Phones are equipped with a BLE interface which will allow you to write applications that can search for an recognize beacons.

Again, the beacon just announces, “here I am” and the application on the mobile device does the real work of “seeing” the beacon and deciding upon the next course of action.

The Retail Connection

One of the most talked about areas for the use of beacons is in a retail environment – and the possibilities are truly endless. 

Here is a sample scenario:

Customer Visit Tracking

It is possible to install beacons various locations within a store and track the following:

  • When the customer entered or exited the store
  • The amount of time spent within the store
  • The departments visited
  • The amount of time spent within a department
  • Purchases

All of these data points are primarily centered around a customer having an application on their phone that can interact with the beacons and send the data back the the cloud-based collection system.

Data Analysis

The one thing you really need to be careful of when capturing beacon data is the amount of data produced. The data flow will dictate the design of your beacon data storage and what tools you use to perform the analysis.  There are several possibilities here:

  • Estimote has built-in analytics for their beacons
  • You can roll your own using Azure App Services to both record the data and perform analysis
  • Add it to your internal SQL Server data system and use tools such as PowerBI to perform the analysis

The Dynamics CRM Connection

Let me state right up front that Dynamics CRM is not where you put your beacon data. There will, in most cases, be too much data and there are better, faster, and cheaper alternatives for both the storing and analysis, like the ones mentioned above.

After you have collected the data and performed the analysis is when you connect it to Dynamics CRM.  The primary use of any Customer Relationship Management system is to record data about a customer:

  • When do they shop?
  • What do they like to buy?
  • Are they purchasing for them selves or a family member?
  • Do they have a brand-preference or a deal-preference?

Use your analysis tools to deliver that type of information by using data obtained from their purchase history, the beacon data, and your web site. That is how you can improve the interaction of your company with the customer.

Make sure your marketing department makes good use of this new data and delivers to the customer the types of offers that make sense to them.

The key point here is value. You need to constantly be providing value to the customer.  It is not always about you; and yes, you need to sell things to stay in business, but it is much easier to sell to people who want to buy.

The Big-Brother Creepiness Factor

This type of process is fairly high on the big-brother creepiness factor but is really saved by the fact that the customer has opted-in to this program by:

  1. Installing the application on their phone
  2. Setting their personal preferences to allow their activities to be tracked

Physical Retail vs. Online Retail

What is so very ironic about this entire conversation is that Online retailers already collect this type of data each and every time a customer visits their web site.  Some are much better than others, but they all do it to a certain extent.

Deploying a technology like beacons to a physical retail store gives that company the ability to collect, and hopefully use wisely, the same types of data that their web site produces.  When you combine those two sets of data together, you can generate a more complete picture of the customer.

Conclusion

All of these things we’ve discussed today are fairly easily done, just remember one extremely key point: Do not be a pest. 

One one likes a pest, either in the online or physical retail world.

Dynamics CRM Developer Tip O’ the Day: Working with Tabs

I learned an important lesson yesterday, again, on working with tabs with Dynamics CRM forms.

There are several ways to reference tabs when writing JavaScript and using the Xrm.Page model.  You may reference the tab by number, like this:

Xrm.Page.ui.tabs.get(2)

Note: Tabs are numbered starting with zero for the first tab.

Or by name, like this:

Xrm.Page.ui.tabs.get("tab2Tab")

It is always a best practice to use the name of the tab instead of the number because if you ever move the tab around the form, then the number will no longer be valid and any JavaScript you have written which references a particular tab in such a manner will start to cause some very strange user experiences.

By using the name of the tab, you will always be referring to the same tab, no matter where it may be located on the form.

In my particular case, this was a Dynamics CRM 2013 installation that had been upgraded from 4.0.  My JavaScript conversion tool, Transformer!, automatically converts the tab references using the number because of the naming convention applied to the converted forms, which is a GUID.

I had merged the original Information form with the new Entity form and in doing so, I had inadvertently moved the tabs out of place.  The logic in JavaScript involved changing the title of a tab as well as showing and hiding one of two different tabs, based on the value of an Option Set field.

I worked around my issue by renaming my tabs from the GUID value to tabxTab, which was the original CRM 4.0 naming format then modified my JavaScript to use that name instead of the number.

By the way, the same practice also applies to form Sections, which are named and referenced in a similar manner.

Dynamics CRM 2015 Spring: Plugin Trace Log

Yay! Finally, the good folks on the Dynamics CRM team have added the ability to log errors that occur in plugins and custom workflow activities.

Plug-In Trace Log

This is a new entity that we can access from the Settings, Customization area:

image

 

Setup

You need to enable the logging of exceptions to the plug-in trace log entity. Navigate to Settings, Administration, System Settings, then select the Customization tab.

image

Change the Enable logging to plug-in trace log setting to Exception.

Usage

Any time you have an unhandled exception in your plug-in or custom workflow activity, a log will be written to the trace log:

image

The detail looks like this:

image

Final Thoughts

This is a huge advance for those of us who develop with Dynamics CRM. Prior to this feature, we found I very difficult to record exception information, especially in CRM Online because any record we recorded to a logging entity was erased and when the transaction was rolled back, which was the common occurrence when exceptions were encountered.

This new entity and feature will be a most welcome addition.