Tuesday 9 October 2012

The Outlook CRM Addin and memory

For the last few weeks we've been fighting a persistent "Microsoft Outlook has encountered an error and needs to close, we're sorry for the inconvenience" message.

We've contacted Microsoft, worked through their troubleshooting, which basically involves:

  • Removing a bunch of addins they've seen some issues with in the past.
  • Making sure that everything is bang up to date.
  • Following most of the instructions in the white paper "Optimizing and Maintaining Client Performance for Microsoft Dynamics CRM 2011 and CRM Online", available from http://www.microsoft.com/en-us/download/details.aspx?id=23261.
But the problem is quite simple.  Outlook uses a fair bit of memory itself, the CRM add in only increases the amount required and IE is running in process.  We've seen Outlook with the CRM start up requiring anything between 250MiB and 750Mib.  CRM's Addin also leaks a bit of memory.

Add all that to a couple of open windows any you find that Outlook will crash as above when round about 1.1GiB of memory is demanded.  The leak makes it more likely to happen over time, leaving CRM windows open, each of which can demand 40 - 100 MiB open makes it more likely to happen.  But the architecture is a bit of a house of cards.

We've noticed that an unhanded exception bubbles almost all the way to the surface in Outlook, they're then eaten before Outlook closes gracefully.  This prevents investigation of errors with tools expecting an un-handled exception.  Microsoft's Debug Diagnostics tool was a huge help finding issues http://www.microsoft.com/en-us/download/details.aspx?id=26798.  This can produce dumps based on certain events like thrown exceptions which can be debugged using Visual Studio.  Microsoft doesn't read these traces properly, they look up the stack see Enterprise Vault or something similar and just blame that.

We found a number of exceptions that would have been handled, a few out of memory exceptions and quite a few assignments to null pointers.  Malloc returns null when it can't allocate memory, so this can also be an indication of a low memory condition.

The 64bit Outlook client runs beautifully, is faster and doesn't run out of memory.  Sadly it took us a few weeks to get to this condition.  Not helped by Microsoft's working assumption that the 32bit add in is a reliable piece of software.

So we've learned from this:
  • Outlook has shoddy error handling, some logging would be lovely.
  • A big CRM solution is unlikely to run in the 32bit Outlook client.
  • The whole lot is running in process.  Add this to bad error handling and a crash anywhere in Outlook, the an add-in, or the CRM add ins IE integration is going to close Outlook.
  • Don't trust Microsoft's engineers to correctly analyse dump files.
  • Make certain you test your solution in Outlook and offline as early as you can.

Monday 7 May 2012

Xrm plug ins beyond the template

We're writing a fair bit of code for Dynamics CRM  at the moment. The team I'm working with have been cutting and pasting code found on Google onto the Visual Studio templates, then losing an awful of of time when things go wrong.

I'm completely new to Dynamics CRM and have been keen to learn, but I'm not used to such faith oriented software development. I'd rather poke around, fix stuff that looks stupid and start to better understand what's going on.

To cut what could be a long story short, I've landed up with a little library of extension methods, entity wrappers, etc to make my code more expressive and my life much easier  I'm going to write about some of these in later posts.  

This library of code has grown to the extent that I really wanted to put this stuff in a common assembly. I followed the ILMerge post from Chris Condron which is pretty easy, as long as you download the project attached to the post. While I was there, I decided to Create my own, generic IPlugin implementation, because the one that is generated as part of the Visual Studio integration is a pretty poor piece of code.

At this point I tried to build and deploy my plugin, with little expectation of success.  It took a bit of fiddling to get the ILMerge step to work.  My first issue came from my attempt to include an assembly compiled for Silverlight.  This is a correct thing to do, but a bad idea with ILMerge, which just sits there and thinks about the problem for a very long time.  I probably went too far while trying to understand the nature of the problem and added too many /lib: /closed and other switches, before finding that Chris's example works fine, as long as I only marked the common assembly as requiring merging.

I then ran into the deployment problems. CRM unhelpfully returns the same "Plug-in assembly does not contain the required types or assembly content cannot be updated" message whatever the issue. It looks like this could mean:
  • Your plugin is replacing another, but doesn't implement all of its steps.
  • An assembly required by the plugin is missing from the target server.
  • The plugin class does not directly implement IPlugin.
It turns out that I should have found Orangegeko's post about this, but I didn't.  Your class may well inherit from a class which implements IPlugin, but your class  has to explicitly implement IPlugin too.  The team who wrote this deployment process may want to consult some reflection documentation.

Having done all this, I now have a plugin class 40 lines long, compiling into a 20K or so assembly and a library with some unit tests.  I now feel like a developer again, rather than somebody trying to copy and paste solutions together.