Industrie und Dienstleistungen
Der ideale Digitalisierungspartner kennt sich nicht nur mit Theorie und Technik, sondern auch mit der Branche seines Kundens aus. In acht Fokusbranchen stellen wir Ihnen ausgewiesene Experten zur Seite, die mit den Prozessen, Prioritäten und Herausforderungen Ihres Fachbereichs vertraut sind.
Kontakt
Fertigungsunternehmen
Seit Langem konzentriert sich proMX darauf, Unternehmen der produzierenden Industrie bei der digitalen Transformation Dynamics 365 zu unterstützen.
proMX Services
proMX analysiert Ihre Geschäftsprozesse und stattet Ihr Unternehmen mit maßgeschneiderten Lösungen aus, um Ihre Herausforderungen zu meistern. In unserem Discovery-Workshop finden wir die passenden Werkzeuge, damit Sie in Zukunft noch produktiver arbeiten können. Legen wir los!
Interessant für Sie
Partners
Indem Sie als Partner der proMX Group die proMX 365 Productivity Suite anbieten, haben Sie die einzigartige Gelegenheit, Ihr Geschäftsportfolio zu erweitern und signifikantes Wachstum zu erzielen.
Werden Sie Partner!
Wir helfen Firmen jeglicher Größe bei der Transformation zu digitalen Unternehmen.
Über uns
proMX ist Ihr Digitalisierungs-Partner. Wir helfen Ihnen, die Prozesse Ihres Unternehmens so zu transformieren, dass Sie agiler, effizienter und wettbewerbsfähiger arbeiten können. Als Microsoft-Partner haben wir jahrelange Erfahrung und herausragende Beziehungen.
Mehr über proMX
Unsere Mission
Wir helfen Firmen jeglicher Größe bei der Transformation zu digitalen Unternehmen.
Frank Bursitzke
2 Jun 2017 | Aktualisiert am: 16 Dez 2022
Expertenbeiträge | 4 Min. Lesezeit

Ich habe einen Windows-Dienst, der sich mit CRM-Systemen ab Version 2011 verbinden können muss. Bisher lautete die Strategie für dieses Szenario, die niedrigste Version aller Abhängigkeiten zu wählen, also CRM SDK 5 (2011) und somit .NET Framework 4.0. Das funktionierte auch für CRM 2011, 2013, 2015 und 2016 OnPremises. Lediglich mit CRM 2016 Online gab es schließlich ein Problem, da das Anmeldeverfahren geändert wurde. Die Anmeldung war nur noch unter Verwendung der aktuellen SDK Version 8.x möglich.

Für dieses Problem gab es zwei offensichtliche Lösungsansätze:

  1. Grundsätzlich gegen die neuste CRM SDK Version kompilieren.
  2. Einen separaten Branch in der Versionsverwaltung pflegen.

Beide Ansätze hatten jedoch entscheidende Nachteile:

  1. Das hätte die Anforderung an die .NET Framework-Version auf .NET 4.5.2 erhöht, was nicht gewünscht war.
  2. Ein zusätzlicher Branch bedeutet zusätzlichen Wartungsaufwand.

Deshalb habe ich einen dritten, eleganteren Lösungsansatz unter Verwendung von msbuild-magic gesucht.

Auch wenn in diesem Beispiel die CRM SDK verwendet wird, lässt sich diese Lösung natürlich auf beliebige Third-Party-Libraries anwenden. Zusätzlich kann auf Grund der verwendeten Compiler-Konstanten auch das Verhalten der Anwendung (z.B. Nutzung neuer bzw. Entfall alter API-Features) beeinflusst werden.

Aufsetzen der Beispiel-Lösung

In der Regel wird man, wenn man vor diesem Problem steht, bereits eine komplexe Lösung haben, daher halte ich es kurz.

Ich verwende für dieses Beispiel eine Konsolenanwendung auf Basis von .NET 4.0. Weiterhin lege ich die verschiedenen Versionen in jeweils eigenen Unterordnern innerhalb eines _lib-Verzeichnisses ab. (Eine Lösung unter Verwendung von nuget-Packages wäre zwar noch eleganter, allerdings habe ich das bisher noch nicht ausprobiert.)

Structure-of-the-example solution
Aufbau der Beispiel-Lösung

Vorbereitung

Zunächst lege ich eine weitere Build-Konfiguration Release_2016 an und kopiere dabei die Einstellungen der vorhandenen Release-Konfiguration.

Anschließend definiere ich in den Projekt-Eigenschaften im Reiter Builds für die neue Konfiguration eine Compiler-Konstante CRM2016 (hier tut es jeder andere Name natürlich auch). Dieser Schritt ist optional und kann für die bedingte Kompilierung von Code-Teilen verwendet werden, für die reine Kompilierung im Sinne dieses Blog-Eintrags ist das jedoch nicht notwendig.

build-configuration-symbol
Build-Konfiguration „Release_2016“ mit Compiler-Konstante

Für die weiteren Schritte muss die Projektdatei selbst bearbeitet werden. Dazu muss das Projekt zunächst über Project Explorer entladen werden (Rechtsklick à Projekt Entladen) und anschließend im XML-Editor bearbeitet werden (Rechtsklick à Projekt ConsoleApplication_Example.csproj bearbeiten).

Bedingte Auswahl der .NET Framework Version

Um die standardmäßig verwendete .NET Framework-Version 4.0 bei Auswahl der Konfiguration „Release_2016“ zu überschreiben, wird der entsprechenden PropertyGroup das TargetFrameworkVersion Element hinzugefügt und auf die Version 4.5.2 festgelegt:


 <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release_2016|AnyCPU'">
  <OutputPath>bin\Release_2016\</OutputPath>
  <DefineConstants>TRACE;CRM2016</DefineConstants>
  <Optimize>true</Optimize>
  <DebugType>pdbonly</DebugType>
  <PlatformTarget>AnyCPU</PlatformTarget>
  <ErrorReport>prompt</ErrorReport>
  <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
  <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
 </PropertyGroup>

Jetzt wird bei Auswahl der Konfiguration „Release_2016“ gegen .NET 4.5.2 kompiliert, für alle anderen nach wie vor gegen .NET 4.0.

Bedingte Auswahl der Third-Party-Assembly

Hier wird es etwas komplizierter. Zunächst müssen die Referenzen auf die Third-Party-Assemblies aus der standardmäßigen ItemGroup entfernt werden. Dazu werden die entsprechenden Reference-Elemente gelöscht.

Anschließend wird mit einem MSBuild Choose Element die entsprechende Assembly aus dem jeweiligen Verzeichnis in einer eigenen ItemGroup wieder hinzugefügt. Bei Auswahl der Konfiguration „Release_2016“ sollen die Assemblies aus dem Unterverzeichnis _lib\CRM 2016, andernfalls aus dem Verzeichnis _lib\CRM 2011 verwendet werden.

Das sieht dann folgendermaßen aus:

<figure>
<pre><code tabindex="0" spellcheck="false"><Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!—snip… -->
   <Choose>
     <When Condition="'$(Configuration)' == 'Release_2016'">
        <ItemGroup>
           <Reference Include="microsoft.crm.sdk.proxy">
              <HintPath>..\..\_lib\CRM 2016\microsoft.crm.sdk.proxy.dll</HintPath>
           </Reference>
           <Reference Include="microsoft.xrm.sdk">
              <HintPath>..\..\_lib\CRM 2016\microsoft.xrm.sdk.dll</HintPath>
           </Reference>
       </ItemGroup>
     </When>
     <Otherwise>
        <ItemGroup>
           <Reference Include="microsoft.crm.sdk.proxy">
              <HintPath>..\..\_lib\CRM 2011\microsoft.crm.sdk.proxy.dll</HintPath>
           </Reference>
           <Reference Include="microsoft.xrm.sdk">
              <HintPath>..\..\_lib\CRM 2011\microsoft.xrm.sdk.dll</HintPath>
           </Reference>
       </ItemGroup>
    </Otherwise>
 </Choose>
</Project>
</code></pre>
</figure>

Ergebnis

Nach dem erneuten Laden des Projekts wird nun in Abhängigkeit der Build-Konfiguration entweder gegen .NET 4.0 und die CRM 2011 SDK oder gegen .NET 4.5.2 und die CRM 2016 SDK kompiliert.
Da ausschließlich MSBuild-Mechanismen verwendet werden, funktioniert die hier beschriebene Lösung sowohl bei der Kompilierung in Visual Studio selbst als auch über automatisierte Builds, z. B. über den Team-Foundation-Server.

Answering