Note: Remember to re-compile the plug-in project for each time you make
changes to the code.
We have provided a more robust interface to make the synchronization of plug-ins,
which ensures that code saved in the source control of the events that should be
registred in MS CRM. As we use scripts, these can easily be built-in to the
current built-script of the solution for deploy automation.
Note: We ensure that plug-in steps are enabled by running the following
functionality, Solution.pluginSteps, after the solution is deployed.
Not everybody has the same approach as we do (we make software solutions) while
working with the MS CRM platform. Therefore you cannot always expect to have a
perfect scenario where the blueprint of the solution is saved to the source
control and from a specific tag, it’s deployed to both the TEST and PROD
environments as a managed package. When we take over other consultancies soltions,
we usually see that they just deploy the Default solution to both TEST and
PROD as an unmananged package. There are a lot of reasons why this is not a
best practice, but lets try to keep this blogpost positive.
Another issue that we sometimes meet is that a customer wants to upgrade to a
newer version of MS CRM and they ask us if we can visualize how many changes
there are from their solution compared to a Vanilla from the version they want
to upgrade to.
Note: Vanilla is the name we use to denominate a MS CRM solution that is not
modified with any configurations or customizations. In other words, standard
Back in the days, MS CRM 4.0, we had the Customization Comparison Utility
which could load two MS CRM customization files and provide a visualization in
order to see what the differences between the source and target are, if any:
This tool helped us a lot in the way that we could always point out to the
customer that they had once again made a change to PROD environment whithout
notifying us and therefore the change would be overwritten by the DEV package
It also gave us the possibility to export all the differences to an Excel
Spreadsheet, where it was a bit easier to make diagrams and other visualizations
for better customer understanding.
Diff of solutions
Because we missed this tool a lot we decided to implement the logic as
a module in Daxif in order to provide this functionality.
It’s very easy to use, lets take the example that we have just created a
solution, see previous How to Daxif, basic setup
blogpost, and we have now retrieved both the managed and unmananged solution
and stored them in our source control:
Note: The only difference is that the assembly was rebuilt before packaging,
therefore, even though there are no code differences, the hash code of the
binary changes due to compilation strategies (non-deterministic) and therefore
not producing the same binary.
Note: In order to get a better view of the summary .CSV file, just convert to
an Excel Spreadsheet, enable Data filters and apply the following filter on
Source (does not contain a dot, which exclude all files paths)
As mentioned in a previous post, and because Daxif is now Open Source, I will
be blogposting on a weekly series of How to Daxif: …. The first topic will
be how to setup Daxif as part of a Visual Studio project.
Note: The only thing we needed to do was to remove the following lines from
our .SLN files
The reason we followed Microsoft on this matter was that we see a lot of other
consultancies creating monolithic frameworks which are almost impossible to
get away from. We would like to think that our approach is a bit more fair
in the way that if our customers would like to replace us, the consultancy
taking over, just need to have the basic understanding on how the Developer
Toolkit for Microsoft Dynamics CRM works.
As you can see it’s more or less the same: Plug-in and Workflow projects are the
same and the CrmPackage is just replaced by Daxif. We have added the BusinessDomain,
generated code from the MS CRM datamodel, and the BusinessLogic, reusability of
code projects; as well as the Blueprint project to store the MS CRM solution in
our source control system.
Daxif has helped us out where the Developer Toolkit for Microsoft Dynamics CRM
wasn’t good enough:
Easily generate strongly typed proxy classes without having to run CrmSvcUtil.exe
Edit and register plug-ins without using the Plug-in registration tool
This component has never worked properly and to solve this issue, we have
added the syncSolution to Daxifs Plugins module. There will be a
blogpost on this topic very soon.
Create new web resources or extract existing web resources, add them to your
solution, edit them, and deploy changes all within Visual Studio.
When adding files to this componenet, it actually moves web ressources to a
specific container (HTML Page, JScript File, Style Sheet, … folders)
which most certanly would break any HTML5 app that was built for MS CRM, no
relative path will work. We have taken the approach that what you see locally
in your source control, should be mapped 1:1 to your MS CRM solution (code
should always be master). We handle this matter in Daxif with the
syncSolution in the WebResources modules. There will also be a
blogpost on this topic soon.
Install Daxif from Nuget and keep updated
Back to the setup of Daxif, the only thing that is needed is to add the Daxif
NuGet package to the Daxif project in Visual Studio:
and ensure regularly that is updated:
The final thing that needs to be done is to execute from inside Visual Studio
the DG.EnsureAssemblies.fsx. This is needed due to some
limitations in Nuget:
Open the script file
Mark all the text (CTRL+A) and send to F# Interactive (ALT+ENTER)
And you should see the following output:
Note: The reason we use F# scripts is:
Intellisense and autocompletion when updating scripts in Visual Studio.
Executing scripts from Visual Studio, no need to leave the IDE.
Re-usability of code made in Daxif.
Typesafe scripts: Scripts will be checked for inconsistency before executed
by the F# interpreter. Neither Cmd or PowerShell can provide this.
Update Auth and Config information
Now all Daxif scripts can be executed but you will still need to update these
two scripts files so their match your current setup:
#r@"Microsoft.Xrm.Sdk.dll"#r@"Delegate.Daxif.dll"(** Open loaded libraries for use *)openMicrosoft.Xrm.Sdk.ClientopenDG.Daxifletlog=LogLevel.Verbose(** Serialize Type *)letxml=SerializeType.XML(** Auth information *)#load@"DG.Delegate.HowToDaxif.AuthInfo.fsx"[<Literal>]letauthType=AuthenticationProviderType.OnlineFederation(** Dev auth & environment information *)[<Literal>]letusrDev=DG.Delegate.HowToDaxif.AuthInfo.usr[<Literal>]letpwdDev=DG.Delegate.HowToDaxif.AuthInfo.pwd[<Literal>]letdomainDev=DG.Delegate.HowToDaxif.AuthInfo.domain[<Literal>]letwsdlDev=@"https://mydev.crm4.dynamics.com/XRMServices/2011/Organization.svc"letwsdlDev'=Uri(wsdlDev)(** Test auth & environment information *)[<Literal>]letusrTest=DG.Delegate.HowToDaxif.AuthInfo.usr[<Literal>]letpwdTest=DG.Delegate.HowToDaxif.AuthInfo.pwd[<Literal>]letdomainTest=DG.Delegate.HowToDaxif.AuthInfo.domain[<Literal>]letwsdlTest=@"https://mytest.crm4.dynamics.com/XRMServices/2011/Organization.svc"letwsdlTest'=Uri(wsdlTest)(** Prod auth & environment information *)[<Literal>]letusrProd=DG.Delegate.HowToDaxif.AuthInfo.usr[<Literal>]letpwdProd=DG.Delegate.HowToDaxif.AuthInfo.pwd[<Literal>]letdomainProd=DG.Delegate.HowToDaxif.AuthInfo.domain[<Literal>]letwsdlProd=@"https://myprod.crm4.dynamics.com/XRMServices/2011/Organization.svc"letwsdlProd'=Uri(wsdlProd)(** Source auth & environment information for data migration *)[<Literal>]letusrSource=DG.Delegate.HowToDaxif.AuthInfo.usr[<Literal>]letpwdSource=DG.Delegate.HowToDaxif.AuthInfo.pwd[<Literal>]letdomainSource=DG.Delegate.HowToDaxif.AuthInfo.domain[<Literal>]letwsdlSource=@"https://SOURCE.api.crm4.dynamics.com/XRMServices/2011/Organization.svc"letwsdlSource'=Uri(wsdlSource)(** Target auth & environment information for data migration *)[<Literal>]letusrTarget=DG.Delegate.HowToDaxif.AuthInfo.usr'[<Literal>]letpwdTarget=DG.Delegate.HowToDaxif.AuthInfo.pwd'[<Literal>]letdomainTarget=DG.Delegate.HowToDaxif.AuthInfo.domain'[<Literal>]letwsdlTarget=@"https://TARGET.api.crm4.dynamics.com/XRMServices/2011/Organization.svc"letwsdlTarget'=Uri(wsdlTarget)(** Shared environment information *)letrootFolder=__SOURCE_DIRECTORY__letsolutions=rootFolder+@"\solutions\"
let translations = rootFolder + @"\translations\"
let metadata = rootFolder + @"\metadata\"
let data = rootFolder + @"\data\"
let state = rootFolder + @"\state\"
let associations = rootFolder + @"\associations\"
let mapping = rootFolder + @"\mapping\"
let imported = rootFolder + @"\imported\"
let webresources = rootFolder + @"\..\..\WebResources\src\"
let tools = rootFolder + @"\..\..\..\Tools\"
let pubPrefix = @"dg"
let pubName = @"delegateas"
let pubDisplay = @"DelegateA/S"
let solution = @"HowToDaxif"
let solDisplay = @"HowToDaxif"
Create your publisher and solution
When this is done, you should be able to create your Publisher and Solution by
Note: As I created the publisher before, Daxif will give an error as duplicate
publishers are not allowed
We don’t make MS CRM solutions, but software solutions
We tend to say that we don’t create MS CRM solution but software solutions. As
you can see, by combining Daxif with our XrmFramework (MS Developer Toolkit) We
are able to spend less time with the technical stuff that just should work
everytime, automation by removing the human part will always ensure a more
robust approach, and by spending more time implementing business logic, we think
that we are giving our customers more value for their money.
Last CRMUG meeting, 2015-11-20 @ BRFkredit A/S, we heard that a lot of members
had some difficulties in using the Microsoft Solution Packager tool.
As we at Delegate A/S have been using the tool since MS CRM 2011. This allows us
to store the blueprint of our solutions in the code repositories, which then
gives us the possibility to recreate a solution based on a code commit tag. By
using this approach, it’s easier to maintain a solution as we are just creating
software and hereby we can use known approaches to Application Lifecycle
Therefore we would like to showcase a demo where we go from A to Z explaining
every step. Code samples are available @
What is it?
Microsoft defines SolutionPackager as a tool that can reversibly decompose a
Microsoft Dynamics CRM compressed solution file into multiple XML files and
other files so that these files can be easily managed by a source control
Application Lifecycle Management (ALM): By splitting the solutions
customizations file into smaller parts which can be stored in a source control
system, it gives us the possibility to re-create the solution at any given
code commit which is almost indispensable when making/maintaining software
Multiple developers: It will also allow several people working with their
own local solution and when a component is ready, then merge into the stagging
solution which will be built and deployed to a TEST solution and afterwards to
How to use it? (“correctly”)
Microsoft states: “When the SolutionPackager tool extracts the component files
it will not overwrite existing component files of the same name if the file
contents are identical. In addition, the tool honors the read-only attribute on
component files producing a warning in the console window that particular files
were not written. This enables the user to check out, from source control, the
minimal set of files that are changing. The /clobber parameter can
be used to override and cause read-only files to be written or deleted. The
/allowWrite parameter can be used to assess what impact an extract
operation has without actually causing any files to be written or deleted. Use
of the /allowWrite parameter with verbose logging is effective”.
“This enables the user to check out, from source control, the minimal set of
files that are changing. The /clobber parameter can be used to
override and cause read-only files to be written or deleted”.
This is the main reason why TFS as source control is broken. If you have
made a change to a file (Edit) and afterwards delete it, then TFS will complain
that it can’t commit the edited file because it’s deleted (it’s stores both
actions). Also there is the issue that TFS handles files that are read-only in
the file system as committed and those who are not as checked-out. Unless you
have to, please don’t use TFS as your source control.
It’s possible to make SolutionPackager work with TFS, but we discovered it made
us change our natural code commit behavior (always commit before Extract/Pack
even though code was not ready). If you want to set up TFS correctly, please
follow this guide:
Guide to setup TFS the wrong way …
Guide to setup TFS correctly
What we usually see
Add assemblies to DEV environment with Plug-in registration tool
Assemblies are built with the Debug Profile
Manually extraction of Default.zip (not even a subset solution)
Eventually save the hole .ZIP file in the source control system (SVN, TFS, …)
Impossible to work with on a multiple DEV setup (diff of files in Visual
Studio is not possible)
Deploy extracted .ZIP file from DEV -> TEST and go through Test Cases
Finally deploy extracted .ZIP from DEV -> PROD
What we would like to see
Add assemblies to DEV environment with Plug-in registration tool (or better tooling :))
Assemblies are built with the Debug Profile
Retrieve the unmanaged and managed subset solution from DEV (ex: FooBar.zip)
Extract the solution to the source control system. Managed and Unmanaged
extracted solution are saved in the same folder structure. It’s important to
use the SolutionPackager mapping file in order to tell the tool that code
(Plug-in and Workflows as well as Web Resources) are handled by a Visual
Merge diff locally before committing to the source control system as you
would normally do when you are working on a software solution
Deploy the packed .ZIP from the source control system GIT -> TEST and go through Test Cases
Ensure that Assemblies are built with the Release Profile
Finally deploy the packed .ZIP from the source control GIT -> PROD
Two very important remarks:
SolutionPackager doesn’t like long paths. Your source control folder should be
as close to your drives root:
Wrong: C:\Users\foo\Documents\Visual Studio 2015\DG.CRMUG\DG.CRMUG.FooBar.sln
When pointing to assemblies in the SolutionPackager mapping file, names must not have dots:
Samples based on Live Demo at CRMUG
We showcased the following scenario in order to point out how important it is
not to deploy Debugged code to PROD:
Retrieve solution from DEV and Extract (Use Visual Studio to see Diff between CRM and GIT)
Deploy .ZIP file from DEV -> TEST and see it fail
Show code where if Debug, code will fail
Pack from source control and deploy to TEST and see it succeed
thrownewException("Debug code shouldn't go to TEST/PROD");#endif
Plug-in code that fails when compiled with the Debug Profile:
Delegate.Daxif is released under our Open Source License
Due to this fact, I will blogpost on a weekly series of How to Daxif: …
based on a specific topic each time and where we will show the features the tool
has to offer in order to create more robust MS CRM solutions. Stay tuned.