So wählen Sie unterschiedliche app.config für mehrere Build-Konfigurationen aus

115

Ich habe ein DLL-Projekt , das MSTest-Integrationstests enthält. Auf meinem Computer bestehen die Tests, und ich möchte, dass dies auch auf einem CI-Server geschieht (ich verwende TeamCity). Die Tests schlagen jedoch fehl, da ich einige Einstellungen in app.config anpassen muss. Aus diesem Grund habe ich mir überlegt, eine separate zweite app.config-Datei zu haben, die die Einstellungen für den CI-Server enthält.

Also hätte ich gerne

/ Sln
 / Proj
  app.config (Ich denke, dies wird von VS benötigt)
  app.Release.config (Dies ist eine eigenständige unabhängige Konfigurationsdatei)

Wenn ich also Konfiguration in Build-Konfiguration auf CI freigeben auswähle, möchte ich die Datei app.Release.config anstelle von app.config verwenden

Problem
Dies scheint für einfache DLL-Projekte nicht einfach zu sein. Für Webprojekte kann ich Webkonfigurationsumwandlungen durchführen. Ich habe einen Hack gefunden, wie man diese Transformationen für ein DLL-Projekt macht, aber ich bin kein großer Fan von Hacks.

Frage
Was ist ein Standardansatz zum Optimieren von app.config-Dateien in Abhängigkeit von der Build-Konfiguration für .NET-Projekte (wie Debug, Release, ...)?

oleksii
quelle

Antworten:

154

Verwenden Sie das SlowCheetah- Plugin. Weitere Optionen und Details zur Verwendung von SlowCheetah finden Sie weiter.

Wie Sie bereits bemerkt haben, gibt es keine standardmäßige und einfache Möglichkeit, verschiedene Konfigurationsdateien für ein Projekt vom Typ Bibliothekstyp (DLL) zu verwenden. Der Grund ist, dass das aktuelle Denken ist: "Sie müssen nicht"! Framework-Entwickler gehen davon aus, dass Sie eine Konfiguration für die ausführbare Datei benötigen: eine Konsole, einen Desktop, ein Web, eine mobile App oder etwas anderes. Wenn Sie anfangen, die Konfiguration für eine DLL bereitzustellen , erhalten Sie möglicherweise etwas, das ich als Konfigurationshölle bezeichnen kann . Möglicherweise verstehen Sie nicht mehr (leicht), warum diese und jene Variablen so seltsame Werte haben, die scheinbar aus dem Nichts kommen.

"Warte", - du kannst sagen, "aber ich brauche das für meine Integration / Unit-Tests, und es ist eine Bibliothek!". Und das ist wahr und das können Sie tun (nur eine auswählen, nicht mischen):

1. SlowCheetah - transformiert die aktuelle Konfigurationsdatei

Sie können SlowCheetah installieren - ein Visual Studio-Plug-In, das alle XML-Stöße (oder Transformationen) auf niedriger Ebene für Sie ausführt . So funktioniert es kurz:

  • Installieren Sie SlowCheetah und starten Sie Visual Studio neu (Visual Studio> Extras> Erweiterungen und Updates ...> Online> Visual Studio-Galerie> Suche nach "Slow Cheetah")
  • Definieren Sie Ihre Lösungskonfigurationen ( Debug und Release sind standardmäßig vorhanden), Sie können weitere hinzufügen (Rechtsklick auf die Lösung in Projektmappen-Explorer > Konfigurationsmanager ... > Aktive Lösungskonfiguration > Neu ...
  • Fügen Sie bei Bedarf eine Konfigurationsdatei hinzu
  • Klicken Sie mit der rechten Maustaste auf Konfigurationsdatei> Transformation hinzufügen
    • Dadurch werden Transformationsdateien erstellt - eine pro Ihrer Konfiguration
    • Transformationsdateien funktionieren als Injektoren / Mutatoren. Sie finden den erforderlichen XML-Code in der ursprünglichen Konfigurationsdatei und fügen neue Zeilen ein oder mutieren den erforderlichen Wert, unabhängig davon, was Sie dazu auffordern

2. Spielen Sie mit der .proj-Datei - kopieren Sie eine ganz neue Konfigurationsdatei durch Kopieren um

Ursprünglich von hier genommen . Es ist eine benutzerdefinierte MSBuild-Aufgabe, die Sie in die Visual Studio- PROJ- Datei einbetten können . Kopieren Sie den folgenden Code und fügen Sie ihn in die Projektdatei ein

<Target Name="AfterBuild">
    <Delete Files="$(TargetDir)$(TargetFileName).config" />
    <Copy SourceFiles="$(ProjectDir)\Config\App.$(Configuration).config"
          DestinationFiles="$(TargetDir)$(TargetFileName).config" />
</Target>

Erstellen Sie nun im Projekt einen Ordner mit dem Namen Configund fügen Sie dort neue Dateien hinzu: App.Debug.config , App.Release.config usw. Abhängig von Ihrer Konfiguration wählt Visual Studio nun die Konfigurationsdatei aus einem ConfigOrdner aus und benennt sie in das Ausgabeverzeichnis um. Wenn Sie also das PatternPA.Test.Integration- Projekt und eine Debug- Konfiguration ausgewählt haben, finden Sie im Ausgabeordner nach dem Build eine PatternPA.Test.Integration.dll.config- Datei, die kopiert Config\App.Debug.configund anschließend umbenannt wurde.

Dies sind einige Hinweise, die Sie in den Konfigurationsdateien hinterlassen können

<?xml version="1.0" encoding="utf-8"?>
<configuration>

    <!-- This file is copied and renamed by the 'AfterBuild' MSBuild task -->

    <!-- Depending on the configuration the content of projectName.dll.config 
        is fully substituted by the correspondent to build configuration file 
        from the 'Config' directory. -->

</configuration>

In Visual Studio können Sie so etwas haben

Projektstruktur

3. Verwenden Sie Skriptdateien außerhalb von Visual Studio

Jedes Build-Tool (wie NAnt , MSBuild ) bietet Funktionen zum Transformieren von Konfigurationsdateien in Abhängigkeit von der Konfiguration. Dies ist nützlich, wenn Sie Ihre Lösung auf einer Build-Maschine erstellen, auf der Sie mehr Kontrolle darüber haben müssen, was und wie Sie das Produkt für die Veröffentlichung vorbereiten.

Beispielsweise können Sie die Aufgabe der Web Publishing-DLL verwenden, um eine beliebige Konfigurationsdatei zu transformieren

<UsingTask AssemblyFile="..\tools\build\Microsoft.Web.Publishing.Tasks.dll"
    TaskName="TransformXml"/>

<PropertyGroup>
    <!-- Path to input config file -->  
    <TransformInputFile>path to app.config</TransformInputFile>
    <!-- Path to the transformation file -->    
    <TransformFile>path to app.$(Configuration).config</TransformFile>
    <!-- Path to outptu web config file --> 
    <TransformOutputFile>path to output project.dll.config</TransformOutputFile>
</PropertyGroup>

<Target Name="transform">
    <TransformXml Source="$(TransformInputFile)"
                  Transform="$(TransformFile)"
                  Destination="$(TransformOutputFile)" />
</Target>
oleksii
quelle
Ihre zweite Lösung funktioniert einwandfrei, jedoch nicht zum Veröffentlichen von Webprojekten. Nach dem Veröffentlichen eines ASP.NET-Projekts wird die ursprüngliche web.config veröffentlicht.
Massood Khaari
3
@MassoodKhaari Sie müssen sicherstellen, dass diese Aufgabe für das Veröffentlichungsziel aufgerufen wird. Wenn Sie ein Projekt veröffentlichen, wird ein separates Build-Ziel aufgerufen, das möglicherweise nicht standardmäßig aufgerufen wird AfterBuild. Während der typischen Kompilierung wird das AfterBuildZiel standardmäßig aufgerufen. Es sollte eine schnelle Lösung für den Veröffentlichungsfall geben
oleksii
1
Verwendete deine zweite Methode (irgendwie). Wir gingen zum Projekteigenschaften und bearbeitet die Before die kopiert werden App.<Target>.configüber die App.configim Projekt dir , nicht die Ausgabe Richt.
SparK
@oleksii Du hast recht. Ich konnte jedoch immer noch nicht das Ziel finden, das mein Webveröffentlichungsprozess verwendet (in Visual Studio 2013).
Massood Khaari
1
Ich verwende die zweite Methode, musste jedoch dem AfterBuild-Ziel eine Bedingung hinzufügen, um sicherzustellen, dass die Datei vor dem Löschen tatsächlich vorhanden ist. Ich habe eine Debug-Build-Konfiguration, die im Grunde nur die Standarddatei App.config verwendet, aber ich hatte keine App.Debug.config, was bedeutete, dass der Build-Schritt fehlschlagen würde. Ich habe gerade hinzugefügt Condition="Exists('$(ProjectDir)App.$(Configuration).config')".
Siewers
23

Sie können den folgenden Ansatz ausprobieren:

  1. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt und wählen Sie Projekt entladen .
  2. Das Projekt wird entladen. Klicken Sie erneut mit der rechten Maustaste auf das Projekt und wählen Sie <IhrProjektname> .csproj bearbeiten .
  3. Jetzt können Sie die Projektdatei in Visual Studio bearbeiten.
  4. Suchen Sie die Stelle in der * .csproj-Datei, an der Ihre Anwendungskonfigurationsdatei enthalten ist. Es wird so aussehen:
    <ItemGroup>
        <Keine Include = "App.config" />
    </ ItemGroup>
  1. Ersetzen Sie diese Zeilen durch:
    <ItemGroup Condition = "'$ (Konfiguration)' == 'Debug'">
        <Keine Include = "App.Debug.config" />
    </ ItemGroup>

    <ItemGroup Condition = "'$ (Konfiguration)' == 'Release'">
        <Keine Include = "App.Release.config" />
    </ ItemGroup>

Ich habe diesen Ansatz für app.configDateien nicht ausprobiert , aber er hat mit anderen Elementen von Visual Studio-Projekten gut funktioniert. Sie können den Erstellungsprozess fast beliebig anpassen. Wie auch immer, lassen Sie mich das Ergebnis wissen.

vharavy
quelle
Tnx für die Antwort, aber das funktioniert nicht mit app.config. VS erfordert eine obligatorische app.configund wendet keine Release-Konfiguration an, wenn ich VS Build oder Teamcity VS SLN Build Runner verwende.
Oleksii
2
Hier erklärt, wie es geht: Aktivieren Sie app.debug.config app.release.config
Gabrielizalo
1
Warum hat diese Antwort so viele Stimmen? Ich habe es versucht und es funktioniert nicht. Tatsächlich gibt es sowohl im Debug- als auch im Release-Modus keine App.config-Datei und daher keine entsprechende Datei im Ausgabeordner. Die Dateien App.Debug.config und App.Release.config haben für Visual Studio keine Bedeutung.
MarkusParker
Es funktioniert nicht: .csproj kann nicht geöffnet werden, Fehlermeldung "Elemente außerhalb der Zielelemente müssen enthalten: Einschließen, Aktualisieren oder Entfernen"
Elo
12

Sie sollten ConfigGen in Betracht ziehen . Es wurde zu diesem Zweck entwickelt. Es wird eine Konfigurationsdatei für jeden Bereitstellungscomputer basierend auf einer Vorlagendatei und einer Einstellungsdatei erstellt. Ich weiß, dass dies Ihre Frage nicht speziell beantwortet, aber es könnte Ihr Problem beantworten.

Anstelle von Debug, Release usw. haben Sie möglicherweise Test, UAT, Produktion usw. Sie können auch unterschiedliche Einstellungen für jeden Entwicklercomputer festlegen, sodass Sie eine für Ihren Entwicklungscomputer spezifische Konfiguration erstellen und ändern können, ohne die Bereitstellung eines anderen zu beeinträchtigen .

Ein Anwendungsbeispiel könnte sein ...

<Target Name="BeforeBuild">
    <Exec Command="C:\Tools\cfg -s $(ProjectDir)App.Config.Settings.xls -t       
        $(ProjectDir)App.config.template.xml -o $(SolutionDir)ConfigGen" />

    <Exec Command="C:\Tools\cfg -s $(ProjectDir)App.Config.Settings.xls -t
        $(ProjectDir)App.config.template.xml -l -n $(ProjectDir)App.config" />
</Target>

Wenn Sie dies in Ihre .csproj-Datei einfügen und die folgenden Dateien haben ...

$(ProjectDir)App.Config.Settings.xls

MachineName        ConfigFilePath   SQLServer        

default             App.config      DEVSQL005
Test                App.config      TESTSQL005
UAT                 App.config      UATSQL005
Production          App.config      PRODSQL005
YourLocalMachine    App.config      ./SQLEXPRESS


$(ProjectDir)App.config.template.xml 

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
   <configuration>
   <appSettings>
       <add key="ConnectionString" value="Data Source=[%SQLServer%]; 
           Database=DatabaseName; Trusted_Connection=True"/>
   </appSettings>
</configuration>

... dann wird dies das Ergebnis sein ...

Ab dem ersten Befehl wird eine Konfigurationsdatei generiert, die für jede in der xls-Datei angegebene Umgebung im Ausgabeverzeichnis $ (SolutionDir) ConfigGen abgelegt wird

.../solutiondir/ConfigGen/Production/App.config

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
   <configuration>
   <appSettings>
       <add key="ConnectionString" value="Data Source=PRODSQL005; 
           Database=DatabaseName; Trusted_Connection=True"/>
   </appSettings>
</configuration>

Ab dem zweiten Befehl wird die auf Ihrem Entwicklungscomputer verwendete lokale App.config durch die generierte Konfiguration ersetzt, die durch den lokalen Schalter (-l) und den Dateinamenschalter (-n) angegeben wird.

Daniel Dyson
quelle
2
Tnx für die Antwort, das sieht nicht schlecht aus. Es gibt jedoch einige Nachteile: Es werden nur 75 Downloads angezeigt (daher ist es nicht ausgereift) und es funktioniert nur mit XLS oder XLSX. Ich möchte mich für einfache Operationen nicht wirklich auf ein anderes benutzerdefiniertes Dokumentformat verlassen. Ich suchte nach einem Standardansatz ...
oleksii
2
Fairer Punkt, obwohl 194 Downloads auf CodePlex stehen, ist xls eine Tabelle, kaum ein benutzerdefiniertes Format, und ich kenne drei große Investmentbanken, die dies für die Verwendung genehmigt haben. Wenn es also gut genug für sie ist ... Auch eine Zu den derzeit angeforderten Funktionen gehört die Verwendung von XML für die Einstellungen. Es ist fast fertig, aber ich bevorzuge trotzdem den Tabellenkalkulationsansatz. Es ist viel einfacher, jede Einstellung für jede Umgebung in einer tabellarischen Ansicht zu sehen
Daniel Dyson
Wir befinden uns jetzt in der Endphase des Testens einer Version von configGen, mit der Klartextdateien und nicht nur XML generiert werden können. Wenn Sie also umgebungsspezifisches CSS, SQL, Javascript usw. generieren möchten, behalten Sie die configGen-Site im Auge
Daniel Dyson
danke Daniel für die Lösung, genau das habe ich gesucht. Ich werde es versuchen.
Bhupinder Singh
10

Mit dem gleichen Ansatz wie Romeo habe ich ihn an Visual Studio 2010 angepasst:

 <None Condition=" '$(Configuration)' == 'Debug' " Include="appDebug\App.config" />

 <None Condition=" '$(Configuration)' == 'Release' " Include="appRelease\App.config" />

Hier müssen Sie beide App.config-Dateien in verschiedenen Verzeichnissen (appDebug und appRelease) aufbewahren. Ich habe es getestet und es funktioniert gut!

tem peru
quelle
3

Ich verwende das XmlPreprocess-Tool zur Bearbeitung von Konfigurationsdateien. Es wird eine Zuordnungsdatei für mehrere Umgebungen (oder in Ihrem Fall mehrere Build-Ziele) verwendet. Sie können die Zuordnungsdatei mit Excel bearbeiten. Es ist sehr einfach zu bedienen.

Ludwo
quelle
3

SlowCheetah und FastKoala aus der VisualStudio-Galerie scheinen sehr gute Tools zu sein, die bei diesem Problem helfen.

Wenn Sie jedoch Add-Ins vermeiden oder die Prinzipien verwenden möchten, die sie während Ihrer Build- / Integrationsprozesse ausführlicher implementieren, ist das Hinzufügen dieser zu Ihren msbuild * proj-Dateien eine Kurzform.

Hinweis: Dies ist mehr oder weniger eine Überarbeitung der Antwort Nr. 2 von @ oleksii.

Dies funktioniert für EXE- und DLL-Projekte:

  <Target Name="TransformOnBuild" BeforeTargets="PrepareForBuild">
    <TransformXml Source="App_Config\app.Base.config" Transform="App_Config\app.$(Configuration).config" Destination="app.config" />
  </Target>

Dies funktioniert für Webprojekte:

  <Target Name="TransformOnBuild" BeforeTargets="PrepareForBuild">
    <TransformXml Source="App_Config\Web.Base.config" Transform="App_Config\Web.$(Configuration).config" Destination="Web.config" />
  </Target>

Beachten Sie, dass dieser Schritt bereits vor Beginn des eigentlichen Builds ausgeführt wird. Die Umwandlung der Konfigurationsdatei erfolgt im Projektordner. Damit die transformierte web.config beim Debuggen verfügbar ist (ein Nachteil von SlowCheetah).

Denken Sie daran, dass beim Erstellen des Ordners App_Config (oder wie auch immer Sie ihn aufrufen möchten) die verschiedenen Zwischenkonfigurationsdateien eine Build-Aktion = Keine und Kopieren in Ausgabeverzeichnis = Nicht kopieren haben sollten.

Dies kombiniert beide Optionen in einem Block. Die entsprechende wird basierend auf den Bedingungen ausgeführt. Die TransformXml-Aufgabe wird jedoch zuerst definiert:

<Project>
<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.Tasks.dll" />
<Target Name="TransformOnBuild" BeforeTargets="PrepareForBuild">
    <TransformXml Condition="Exists('App_Config\app.Base.config')" Source="App_Config\app.Base.config" Transform="App_Config\app.$(Configuration).config" Destination="app.config" />
    <TransformXml Condition="Exists('App_Config\Web.Base.config')" Source="App_Config\Web.Base.config" Transform="App_Config\Web.$(Configuration).config" Destination="Web.config" />
</Target>

Eniola
quelle
Ich habe es gerade in Visual Studio 2017 versucht und es funktioniert nicht. Schießen. Ich hatte wirklich gehofft, dass es funktionieren würde, weil es am einfachsten zu implementieren scheint.
Greg Burghardt
Die TransformXml-Task ist in den Beispielen nicht definiert. Ich füge einen Eintrag hinzu. Sie können es in einer mycustom.targets-Datei definieren, die in all Ihren Startprojekten in Ihrer Lösung enthalten ist.
Eniola
@ GregBurghardt, möchtest du es jetzt versuchen?
Eniola
Ich könnte es versuchen. Ich habe das Config Transform-Plugin für Visual Studio installiert, und das hat sehr gut funktioniert. Ich frage mich eigentlich, ob das Plugin im Grunde das tut, was Ihre Antwort tut.
Greg Burghardt
Okay, lass mich wissen, wie es geht.
Eniola
1

Überprüfen Sie, ob die XDT-Transformations-Engine (web.config) Ihnen helfen kann. Derzeit wird es nur nativ für Webprojekte unterstützt, aber technisch gesehen hindert Sie nichts daran, es in anderen Anwendungstypen zu verwenden. Es gibt viele Anleitungen zur Verwendung von XDT durch manuelles Bearbeiten der Projektdateien, aber ich habe ein Plugin gefunden, das hervorragend funktioniert: https://visualstudiogallery.msdn.microsoft.com/579d3a78-3bdd-497c-bc21-aa6e6abbc859

Das Plugin hilft nur beim Einrichten der Konfiguration, es wird nicht zum Erstellen benötigt und die Lösung kann auf anderen Computern oder auf einem Build-Server erstellt werden, ohne dass das Plugin oder andere Tools erforderlich sind.

TGasdf
quelle
Dies sollte jetzt die Antwort sein. Habe es gerade auf VS 2017 ausprobiert und es funktioniert wie ein Zauber. Sie müssen das Projekt nicht veröffentlichen. Baue es einfach. Funktioniert hervorragend für unser Testprojekt zur Verwendung in unserem Build für die kontinuierliche Integration, sodass wir Selenium-Tests im Headless-Modus ausführen können, sie jedoch lokal mit geöffnetem Browser ausgeführt werden. +1.000.000 wenn ich könnte.
Greg Burghardt
1

Ich habe dieses Thema mit der Lösung gelöst, die ich hier gefunden habe: http://www.blackwasp.co.uk/SwitchConfig.aspx

Kurz gesagt, was sie dort angeben, ist: "durch Hinzufügen eines Post-Build-Ereignisses. [...] Wir müssen Folgendes hinzufügen:

if "Debug"=="$(ConfigurationName)" goto :nocopy
del "$(TargetPath).config"
copy "$(ProjectDir)\Release.config" "$(TargetPath).config"
:nocopy
Janbro
quelle
Bei weitem die einfachste Methode, um eine sehr einfache und wesentliche Funktion zu erledigen, die von Überdenkern vermasselt wurde! Danke Janbro.
BoiseBaked
1

Ich habe gute Dinge über SlowCheetah gehört, konnte es aber nicht zum Laufen bringen. Ich habe Folgendes getan: füge jedem Tag ein Tag für eine bestimmte Konfiguration hinzu.

Ex:

<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'UAT|AnyCPU'">
    <OutputPath>bin\UAT\</OutputPath>
    <PlatformTarget>AnyCPU</PlatformTarget>
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
    <AppConfig>App.UAT.config</AppConfig>
  </PropertyGroup>
Mike
quelle
Dies scheint eine weitere supereinfache Möglichkeit zu sein, app.config-Dateien gemäß der Build-Konfiguration zu ändern. Mike, hast du mit den Standard-Debug- und Release-Konfigurationen getestet?
BoiseBaked
0

Nach einigen Recherchen zum Verwalten von Konfigurationen für Entwicklung und Builds usw. habe ich beschlossen, meine eigenen zu rollen. Ich habe sie auf bitbucket unter folgender Adresse verfügbar gemacht: https://bitbucket.org/brightertools/contemplate/wiki/Home

Diese mehreren Konfigurationsdateien für mehrere Umgebungen sind ein grundlegendes Tool zum Ersetzen von Konfigurationseinträgen, das mit jedem textbasierten Dateiformat funktioniert.

Hoffe das hilft.

Mark Redman
quelle