»

[15 Feb 2012 | 0 Comments]

 

Introduction

Microsoft Dynamics 2011 has made deployment of customisation much easier than pervious version. However there are some technical limitations you face when using Microsoft Crm Online such as not being able to install stuff on the server (such as putting dll’s in the GAC). One of the great features of the framework is the Early Bound Entity code generator. It is useful to put this in a separate project so it can be re-used across other projects, such as the Plugin and Workflow projects. However to deploy this solution structure to Online you need all the code compiled into a single assembly. This post describes how I solved this problem allowing me to have a common project with business logic shared between the assemblies that get deployed.

The project used in this post

I run a small software company called See The Link. The project I am using as an example is one done for one of my clients that we did a ]Dynamics Crm Online solution for. <plug> i’m always looking out for new business - if you want to hire me please get in touch!</plug>

Solution Setup

This is the solution setup I have. It is based on the Dynamics 2011 toolkit template for Visual Studio 2011. As you can see I have a project for plugins, SeeTheLink.Visalogic.Crm.Plugins, and another project for Workflows, SeeTheLink.Visalogic.Crm.Workflow, (I realise that custom workflows cannot be deployed online yet but will be coming in Q2 this year). The early bound entities have been put in the “SeeTheLink.Visalogic.Crm.XrmEntities’ project.  The last important project is the CrmPackage, this project is created by the dynamics template. I don’t understand all the voodoo that this project type does by it is responsible for deploying the assets to the target Dynamics solution. This is where we need to tap into to make it merge the assemblies before it deploys them.

image

Step 1 – Get ILMerge and the msbuild files

There are some msbuild files you you need. They can be found here:

C:\Program Files (x86)\MSBuild\Microsoft\CRM\

The files are called:

Microsoft.CrmDeveloperTools.CrmClient.targets
Microsoft.CrmDeveloperTools.CrmClient.dll

We need to take copies of these files so we can edit the targets per solution otherwise it will happen for all solutions built on the computer. Copy these to a folder just below the solution, I called mine “Tools”

image

Also put ILMerge.exe in there as well. This is the magic tool that does the merging for us. In the above screenshot I have my solution in the DynamicsSolution folder.

Step 2 – Edit the Microsoft.CrmDeveloperTools.CrmClient.targets file

Edit the in file. Find the <Target Name="BeforeDeploy"> tag. Here we put in the command to use ILMerge command:

<Target Name="BeforeDeploy">
<Exec Command="&quot;$(SolutionDir)Tools\ILMERGE.EXE&quot; /targetplatform:v4,C:\Windows\Microsoft.NET\Framework\v4.0.30319 /keyfile:$(KeyFile) /out:$(PluginMergeOutputName) $(PluginMergeDlls)" />
<Exec Command="&quot;$(SolutionDir)Tools\ILMERGE.EXE&quot; /targetplatform:v4,C:\Windows\Microsoft.NET\Framework\v4.0.30319 /keyfile:$(KeyFile) /out:$(WorkflowMergeOutputName) $(WorkflowMergeDlls)" />
</Target>

Here you might notice that I’m using a few variables:

$(KeyFile)
$(PluginMergeOutputName)
$(PluginMergeDlls)
$(WorkflowMergeOutputName)
$(WorkflowMergeDlls)

We will define these in the CrmPakage project file next.

Step 3 – Edit the CrmPackage project file

Unload the project file

image

Edit the file

image

Find the following line in the file:

<Import Project="$(MSBuildExtensionsPath32)\Microsoft\CRM\Microsoft.CrmDeveloperTools.CrmClient.targets" />

Change it to:

<Import Project="$(SolutionDir)Tools\Microsoft.CrmDeveloperTools.CrmClient.targets" />

This should be the path where we copied the files to in Step1 and edited in Step 2.

We also need to define the variables we used in step2.

Add these in a property group:

<PropertyGroup>
    <KeyFile>"$(SolutionDir)Plugins\SeeTheLink.snk"</KeyFile>
    <PluginMergeDlls>"$(OutputPath)SeeTheLink.Visalogic.Crm.Plugins.dll" "$(OutputPath)SeeTheLink.Visalogic.Crm.XrmEntities.dll"</PluginMergeDlls>
    <PluginMergeOutputName>"$(OutputPath)SeeTheLink.Visalogic.Crm.Plugins.Merged.dll"</PluginMergeOutputName>
    <WorkflowMergeDlls>"$(OutputPath)SeeTheLink.Visalogic.Crm.Workflow.dll" "$(OutputPath)SeeTheLink.Visalogic.Crm.XrmEntities.dll"</WorkflowMergeDlls>
    <WorkflowMergeOutputName>"$(OutputPath)SeeTheLink.Visalogic.Crm.Workflow.Merged.dll"</WorkflowMergeOutputName>
  </PropertyGroup>
this is what the end of the file should look like:
image

The ‘PluginMergedOutputName’ is what the output or the merge will be called. It is therefore important to update the RegisterFile.crmregister file. We will do that after we have reloaded the project:

image

Step 4 – Edit the RegisterFile.crmregister file

In the CrmPackage project there is a file called RegisterFile.crmregister. This contains all the references to the plugins that are required for the deploy project to register the dlls. We want to register the merged file so we have to just rename the reference:

image

Step 5 – Deploy!

When you deploy the package you will see the new steps in the build output

image

A couple of gotchas

If you are registering the same plugins just in a dll with a different name then you will need to un-register any dlls already deployed.

You will also need to add

[assembly: Microsoft.Xrm.Sdk.Client.ProxyTypesAssemblyAttribute()]

to the AssemblyInfo.cs file of the plugin and workflow assemblies so the early bound entities work.

In summary

This allows for having common / other files merged into a single assembly that can then be deployed. This allows for more advance features to be included in Online installations where it is not possible to install 3rd party dlls on the server.