DISCLAIMER:  This is technically unsupported, but works.  If that makes you cringe, then walk away.  If you read it and think it will work for you, then make the decision that's best for you.

Example scenarios:

“I have a a field in an entity.  After deploying a managed solution to production, we decided we don’t need that field any longer.  I removed it from my development environment.  When I deploy an updated version of managed solution in production, the old field is still there.  I know it’s harmless to keep it in production, but I want it gone.”

“I renamed a web resource in development after already deploying it to production in a managed solution.  None of my code references it any longer.  When I deploy an updated version of the managed solution, the old web resource is still there.  I want it gone.”

This was something that stumped me when I started focusing on Dynamics CRM 2011.  Technically, the CRM solution package infrastructure has no way to delete something.  However, Shan McArthur explained to me that there is a way to accomplish deletes.  I plan on using this approach in the next release of my validation sample because I did some significant refactoring since my first release.  The general concept is to:

  • Create a temporary managed solution to “hold” the latest “good bits” using the same publisher
  • Import it on top of your existing managed solution
  • Delete the older managed solution
    • This deletes the older stuff while the “holding” solution prevents the “good bits” from being removed
  • Import the new version of the managed solution
  • Delete “holding” managed solution

Let’s walk through this step by step.  You can download the three files to try this yourself here.  I have two orgs: dev and target.  In my dev org, everything is unmanaged:

image

In my target org, I have already deployed the 1.0 managed solution that was exported from my dev org:

image

If you want to try this out yourself, just import the 1.0 managed solution into your own CRM 2011 org.  Here’s a look at the form in it’s current state:

image

Notice that it has a “delete me” field and web resource.  For version 1.1, in my dev environment,  I went ahead and removed the two items from the form, then deleted the field from the entity:

image

…and and the web resource from the solution:

image

Next, I updated the version to 1.1:

image

Finally, I exported the 1.1 version as a managed solution (make sure all your customizations are published).  Ok, so we have the old and new managed solution version.  How do we create the “holding” solution?  Unzip the 1.1 solution, edit the contents of solution.xml like so:

image

I use _HOLDING in UniqueName and LocalizedName to make it obvious.  After you have saved the changes to the solution.xml file, zip up the contents of the unzipped folder:

image

…and name it something unique.  My conventions is to use a name similar to the latest managed solution it will “hold” for:

image

I replace _managed with _HOLDING in the name of the file.  Ok, now you are ready to accomplish a delete.  If you are still following along using the sample files, then do the following:

  • Import devkeydetDeleteExample_1_0_managed.zip if you haven’t already
  • Import devkeydetDeleteExample_1_1_HOLDING.zip
  • Delete devkeydetDeleteExample_1_0_managed.zip (deletes what’s not in the holding solution)
  • Import devkeydetDeleteExample_1_1_managed.zip (creates the proper UniqueName reference to the items in the holding solution)
  • Delete devkeydetDeleteExample_1_0_HOLDING.zip (removes nothing but the solution based on the temporary UniqueName)

The end result is that you will have the items you deleted in your dev environment deleted in your target environment and the solution UniqueName is maintained.  Thanks again to Shan McArthur for explaining this to me.  This general approach can be applied to other “delete stuff that’s no longer used” scenarios as well.

@devkeydet