How to Reference Assemblies from Plug-ins


8/31/15This post has been edited to reflect that Dynamics CRM does not support ILMerge.  It isn’t blocked, but it isn’t supported, as an option for referencing custom assemblies.

You may have noticed that Microsoft Dynamics CRM 2011 (and CRM 4 before it) does not really have support for referencing custom assemblies from a plug-in assembly. You are limited to .NET Framework assemblies and the public Microsoft Dynamics CRM 2011 Software Development Kit (SDK) assemblies. In Microsoft Visual Studio, your references will look something like this:

clip_image002

If you wanted to reference an assembly that you had written, your options were pretty limited:

  • Register the assembly on disk with any referenced assemblies in the same directory.
  • Register the referenced assembly in the GAC
  • Include the relevant source code in the plug-in assembly

With the introduction of Solutions in Microsoft Dynamics CRM 2011, the first two options are not very manageable (as they require special setup on multiple servers during the installation of the solution). In addition, those options don’t work in Microsoft Dynamics CRM Online, since assemblies must be registered in the database in CRM Online. If you include source code, as the last option suggests, then all of the benefits of a referenced assembly are lost, without gaining any real benefits.

Merging Assemblies

Microsoft Research has published another tool that you may use for referencing custom assemblies (however, please note that it is not officially supported): ILMerge. It is a utility that merges multiple Microsoft .NET assemblies into a single assembly. Although this tool has been produced by Microsoft Research, it has been around since .NET 1.1 and is pretty stable. The newest version of the tool also works with .NET 4.0 (newest version of the CLR), which is how it impacts us. In order to get this example to work, you’ll need to use version 2.10.526.0 or above.

Suppose you created a library, PluginLibrary.dll, and wanted to add it as a reference in your plug-in assembly. If you are using ILMerge, you can do just that. Add a reference to your PluginLibrary.dll and build your project.

clip_image004

Once all of the assemblies have been built, ILMerge is run to merge them. Before we can start merging the assemblies, there are a few steps we need to take to get the tool to work with .NET 4.0. First, a config file (name it ILMerge.exe.config), as defined on the ILMerge web site. For convenience, here’s the file:

<?xml version=1.0?><configuration><startup useLegacyV2RuntimeActivationPolicy=true><requiredRuntime safemode=true imageVersion=v4.0.30319 version=v4.0.30319/></startup></configuration>

If you are running ILMerge on a 64-bit machine, you’ll need to locate the 32-bit version of the .NET 4.0 assemblies. If you don’t do this, ILMerge will attempt to load the 64-bit assemblies. Since the tool is compiled as a 32-bit assembly it will throw a BadImageFormatException while loading a 64-bit assembly. On my machine, these assemblies are located at C:\Windows\Microsoft.NET\Framework\v4.0.30319.

As a side note, since ILMerge cannot load 32-bit assemblies while CRM 2011 requires 64-bit assemblies, plug-in assemblies must be compiled as platform neutral (can be loaded as a 32-bit or 64-bit assembly) in order to work with both ILMerge and CRM 2011.

Now that the environment has been prepared, let’s run the tool:

ilmerge /keyfile:PrivateKey.snk /target:library /copyattrs /targetplatform:v4,C:\Windows\Microsoft.NET\Framework\v4.0.30319/out:CompletePlugin.dll MyPlugin.dll PluginLibrary.dll

A quick explanation of the attributes:

– keyfile: Specifies the key file that should be used to sign the final assembly. An assembly must be signed in order to be registered with CRM 2011, so this is a required parameter.

– target: Indicates that the generated file should be a DLL

– copyattrs: Copies the assembly-level attributes from the assemblies and merges them. This is especially useful if you have included the generated entity classes (from CrmSvcUtil.exe) in your library assembly, as this will ensure that the assembly attribute, ProxyTypesAssemblyAttribute, is present on your merged assembly.

– targetplatform: The version of the .NET framework as well as the path to the assemblies. If you are running the tool on a 32-bit machine, the path is not required.

– out: Specifies the output DLL file name

– List of assemblies: The list of assemblies to be merged

Once the tool completes, the output assembly, CompletePlugin.dll, can be registered with Microsoft Dynamics CRM 2011.

Please note that the merged assembly cannot exceed the maximum assembly size (restricted by CRM 2011).

Links

Cheers,

Michael Scott

Comments (14)

  1. All well and good until unless your assembly contains CRMSVCUTIL.exe generated classes says:

    Hi, I took this recommended approach in the summer against the CTP but it turns out that if your linked assemblies contain any references to code generated entities (CRMSVCUTIL.exe generated classes) you are out of luck! Your code will not work.

  2. Some more experiences that may be useful... says:

    As another commenter mentioned, you cannot access the 'strongly-typed' classes generated by crmsvcutil.exe in your 'linked' library. So your 'linked' assembly needs to use the more generic 'Entity' class to work with CRM entities. For this reason we are still directly adding the strongly-typed class file directly to our plugin projects – the plugin code can then use the strong types directly but any 'helper' classes / methods in the shared assembly are implemented using 'Entity'.

    Also, we ran into a problem with plug-in assemblies signed with encrypted .pfx files, requiring a little two-step workaround to sign the resulting assembly properly – see blog.nerdbank.net/…/how-to-get-ilmerge-to-work-with-pfx.html for details.

    Ken

  3. Michael B. Scott - MSFT says:

    I specifically tested the scenario of strongly-typed entities in a different library assembly than the plug-in and it worked correctly. I tested the scenario with the latest CRM 2011 bits.

    Michael

  4. ClaraJames says:

    Nice Information! I have a question about how can we add plugin in css base sites. I have searched some sites like http://www.csswebstyles.com/ and http://www.beyondfuturetechnologies.com about website creation and they have provided good resource about css.

  5. Itzikbs says:

    From software architecture view, it is a very bad practice.

    I want my code (in enterprise it could be thousands of lines …. )  to manage in n-tier  including  BPL /BL / DAL and not coupled to the plug-in or the CRM

    ItzikBS

  6. ItzikBS says:

    From software architecture view, it is a very bad practice.

    I want my code (in enterprise it could be thousands of lines …. )  to manage in n-tier  including  BPL /BL / DAL and not coupled to the plug-in or the CRM

    ItzikBS

  7. crm expert says:

    This is all nice and informative, but obviously this is a complicated (and dare I say convoluted) procedure that developers have to follow.  How about some Visual Studio integration that does the ILMERGE for us and handles the 64bit nastiness and creates the assembly for us without us having to know all of this gobbledygook.

    As an 'enterprise' developer, I expect Microsoft to provide tools for me that take care of this stuff.

  8. Sozan says:

    Plugins are very effective way to design your website. I have contacted many designers for <a href=http://www.logojin.com/website-design.php>web design</a> and they have give me some excellent advice related to web designing.

    http://www.logojin.com/website-design.php

  9. Ubirajara Segura says:

    One option is Add-As Link the source code into a Visual Studio Project.

    That way you can re-use the same code and deploy a DLL supported by Dynamics CRM.

  10. Ankit Singh says:

    Extremly sorry

    Referenced a lot of blogs but still stuck with ilmerge

    There is no clear documentation for use.

    The Merged dll is not working at all.

  11. Hi @Ankit Singh,

    We do not actually support using ILMerge. You won’t find anything about it in the SDK. But customers might try it at their own risk to get around a problem.

    Take a look at this blog post from Nicolas Nowinski:

    Dynamics CRM and ILMerge: The Easy Way to Merge DLLs for Plugins  

    nicknow.net/dynamics-crm-ilmerge-dll-plugin

    Thanks!

  12. Eric W. Cahoon says:

    Way to go guys!  Give us a blog post that's been referenced for years and then five years later tell us that you don't support using the tool the blog post suggests using.  

    Now, let's get down to figuring out how to handle including 3rd party logic in a supported manor.  Is there any recommendation from MS on how to handle referencing 3rd party libraries in a plugin?  We could look at going the route of migrating the business logic that's reliant on a 3rd party library into a service and then call into the service from the plugin; however, that option would impact performance, require refactoring large portions of code, and adding new functionality for things like security around the service.

  13. Hi @Eric W. Cahoon – thanks for your comments.  We've updated the blog post to reflect that ILMerge is not supported, and have clarified any language that previously indicated that it was supported.  As for the larger question, it is on our radar but at this point has not been prioritized.

  14. Daryl LaBar says:

    I've been able to successfully use ILMerge and CRM online 2015 for creating multiple plugins.  What is the reason for defining this as not being supported?  What sort of gotchas will I run into?

    If using early bound don't forget to add this to your plugin's AssemblyInfo:

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

    and here is the post build event that I use:

    if "$(ConfigurationName)" == "Debug No ILMerge" goto :exit

    REM **** Create ILMerge Directory ****

    md "$(TargetDir)IlMerge"

    REM **** Delete Previous Log ****

    del "$(TargetDir)IlMergeLog.txt"

    REM **** Run IlMerge ****

    "$(SolutionDir)External LibrariesILMerge.exe" /log:"$(TargetDir)IlMergeLog.txt" /keyfile:"$(ProjectDir)MyPluginName.Key.snk" /targetplatform:"v4,c:windowsMicrosoft.NETFrameworkv4.0.30319" /out:"$(TargetDir)IlMerge$(TargetFileName)" "$(TargetPath)" "$(TargetDir)MyFirstDll.dll" "$(TargetDir)MySecondDll.dll" "$(TargetDir)MyThirdDll.dll"

    :exit