589 Stimmen

App.Config Transformation für Projekte, die keine Webprojekte in Visual Studio sind?

Für Visual Studio 2010 Web-basierte Anwendung haben wir Config Transformation Funktionen, durch die wir mehrere Konfigurationsdateien für verschiedene Umgebungen pflegen können. Die gleiche Funktion ist jedoch nicht für App.Config-Dateien für Windows Services/WinForms oder Konsolenanwendungen verfügbar.

Es gibt eine Umgehungslösung, die hier vorgeschlagen wird: Anwendung der XDT-Magie auf App.Config .

Dies ist jedoch nicht ganz einfach und erfordert eine Reihe von Schritten. Gibt es eine einfachere Möglichkeit, dasselbe für app.config-Dateien zu erreichen?

0 Stimmen

Ich bin auf den folgenden Artikel gestoßen, der etwas einfacher zu sein scheint, aber ich habe es nicht selbst ausprobiert. fknut.blogspot.com/2009/11/ Außerdem gibt es eine Funktionsanfrage auf MS Connect, für die es sich lohnen könnte, abzustimmen, damit sie in der nächsten SP oder Version durchgängig berücksichtigt wird. connect.microsoft.com/VisualStudio/rückmeldung/details/564414

641voto

Dan Abramov Punkte 252334

Ich habe mehrere Lösungen ausprobiert, und hier ist die einfachste, die ich persönlich gefunden habe.
Dan in den Kommentaren darauf hingewiesen, dass der Originalbeitrag gehört zu Oleg Sych - Danke, Oleg!

Hier sind die Anweisungen:

1. Fügen Sie dem Projekt eine XML-Datei für jede Konfiguration hinzu.

In der Regel werden Sie Folgendes haben Debug y Release Konfigurationen, also benennen Sie Ihre Dateien App.Debug.config y App.Release.config . In meinem Projekt habe ich für jede Art von Umgebung eine eigene Konfiguration erstellt, so dass Sie vielleicht damit experimentieren möchten.

2. Projekt entladen und .csproj-Datei zur Bearbeitung öffnen

Visual Studio erlaubt Ihnen die Bearbeitung von .csproj Dateien direkt im Editor erstellen - Sie müssen nur das Projekt vorher entladen. Klicken Sie dann mit der rechten Maustaste auf das Projekt und wählen Sie <Projektname>.csproj bearbeiten .

3. Binden Sie App.*.config-Dateien an die Haupt-App.config

Suchen Sie den Abschnitt der Projektdatei, der alle App.config y App.*.config Referenzen. Sie werden bemerken, dass ihre Build-Aktionen eingestellt sind auf None und das ist in Ordnung:

<None Include="App.config" />
<None Include="App.Debug.config" />
<None Include="App.Release.config" />

Als nächstes machen Sie alle Konfigurationsspezifisch Dateien abhängige auf der Haupt App.config Visual Studio gruppiert sie also wie Designer- und Code-Behind-Dateien.

Ersetzen Sie die obige XML-Datei durch die folgende:

<None Include="App.config" />
<None Include="App.Debug.config" >
  <DependentUpon>App.config</DependentUpon>
</None>
<None Include="App.Release.config" >
  <DependentUpon>App.config</DependentUpon>
</None>

4. Aktivieren Sie die Transformationsmagie (immer noch notwendig für Visual Studio Versionen wie VS2019 )

Am Ende der Datei nach

<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

und vor dem Finale

</Project>

fügen Sie die folgende XML-Datei ein - bitte beachten Sie, dass es zwei Schritte gibt, damit die Umwandlung korrekt erfolgt:

  <UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.Tasks.dll" />
  <Target Name="BeforeBuild" Condition="Exists('App.$(Configuration).config')">
    <!-- Generate transformed app config and replace it: will get the <runtime> node and assembly bindings properly populated -->
    <TransformXml Source="App.config" Destination="App.config" Transform="App.$(Configuration).config" />
  </Target>
  <Target Name="AfterBuild" Condition="Exists('App.$(Configuration).config')">
    <!-- Generate transformed app config in the intermediate directory: this will transform sections such as appSettings -->
    <TransformXml Source="App.config" Destination="$(IntermediateOutputPath)$(TargetFileName).config" Transform="App.$(Configuration).config" />
    <!-- Force build process to use the transformed configuration file from now on.-->
    <ItemGroup>
      <AppConfigWithTargetPath Remove="App.config" />
      <AppConfigWithTargetPath Include="$(IntermediateOutputPath)$(TargetFileName).config">
        <TargetPath>$(TargetFileName).config</TargetPath>
      </AppConfigWithTargetPath>
    </ItemGroup>
  </Target>

Jetzt können Sie das Projekt neu laden, es erstellen und genießen App.config Verwandlungen!

ZU IHRER INFORMATION

Stellen Sie sicher, dass Ihr App.*.config Dateien haben die richtige Einstellung:

<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
     <!--magic transformations here-->
</configuration>

4 Stimmen

Vielen Dank dafür! Eine Anmerkung, wenn Sie die neuen .config-Dateien zum Projekt hinzufügen, nachdem Sie die csproj bearbeiten, werden sie unter App.config gruppiert angezeigt. Ich fügte eine vor der Bearbeitung der csproj und im Wesentlichen endete mit zwei Links zu ihm, eine gruppierte und eine solo.

0 Stimmen

Sind Sie sicher, dass Sie alle Originalteile entfernt haben? <None Include=""/> s vor dem Hinzufügen neuer <Content Include=""/> s? Diese Anweisung hat bei mir mehrere Male funktioniert, vielleicht haben Sie also etwas übersehen.

0 Stimmen

Ich habe alle <None> ist verwandt mit .config Dateien. Musste ich dies auch für andere Ressourcen tun?

427voto

Scott Hanselman Punkte 17602

Dies funktioniert nun mit dem in diesem Artikel behandelten Visual Studio AddIn: SlowCheetah - Web.config Transformations-Syntax jetzt verallgemeinert für jede XML-Konfigurationsdatei .

Sie können mit der rechten Maustaste auf Ihre web.config klicken und dann auf "Add Config Transformieren". Wenn Sie dies tun, erhalten Sie eine web.debug.config und eine web.release.config. Sie können auch eine web.whatever.config erstellen, wenn Sie möchten. solange der Name mit einem Konfigurationsprofil übereinstimmt. Diese Dateien sind nur die Änderungen, die Sie vornehmen wollen, keine vollständige Kopie Ihrer web.config.

Man könnte meinen, dass man XSLT verwenden sollte, um eine web.config zu transformieren, aber aber obwohl es sich intuitiv richtig anfühlt, ist es in Wirklichkeit sehr langwierig.

Hier sind zwei Transformationen, eine mit XSLT und dieselbe mit XML Document Transform Syntax/Namensraum. Wie bei allen Dingen gibt es gibt es in XSLT mehrere Möglichkeiten, dies zu tun, aber Sie verstehen die allgemeine Idee. XSLT ist eine verallgemeinerte Baumtransformationssprache, während diese Entwicklung für eine bestimmte Untermenge gängiger Szenarien optimiert ist. Aber, das Aber das Tolle ist, dass jede XDT-Transformation ein .NET-Plugin ist, so dass Sie selbst erstellen.

<?xml version="1.0" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="@*|node()">
  <xsl:copy>           
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>
<xsl:template match="/configuration/appSettings">
  <xsl:copy>
    <xsl:apply-templates select="node()|@*"/>
    <xsl:element name="add">
      <xsl:attribute name="key">NewSetting</xsl:attribute>
      <xsl:attribute name="value">New Setting Value</xsl:attribute>
    </xsl:element>
  </xsl:copy>
</xsl:template>
</xsl:stylesheet>

Oder das Gleiche über die Bereitstellungstransformation:

<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
   <appSettings>
      <add name="NewSetting" value="New Setting Value" xdt:Transform="Insert"/>
   </appSettings>
</configuration>

0 Stimmen

Oh, das ist süß! Habe eine App mit zahlreichen Konfigurationsdateien (log4net, nHibernate, web.config) und daran erinnern, sie alle zu ändern war ein bisschen ein Schmerz. Ich freute mich nicht auf das Verschieben des Codes in CruiseControl.NET entweder aber sieht aus wie das ist ein Kinderspiel zu.

10 Stimmen

FYI, SlowCheetah war eine fantastische Erweiterung, die nun nach VS 2014 nicht mehr unterstützt wird. Durch den Autor, Sayed Ibrahim Hashimi, sedodream.com/2014/08/11/… .

0 Stimmen

@AnilNatha Wo steht, dass sie den Support einstellen werden?

149voto

Alec Punkte 1639

Eine andere Lösung, die ich gefunden habe, ist NICHT die Transformationen zu verwenden, sondern nur eine separate Konfigurationsdatei, z. B. app.Release.config. Fügen Sie dann diese Zeile zu Ihrer csproj-Datei hinzu.

  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
    <AppConfig>App.Release.config</AppConfig>
  </PropertyGroup>

Dadurch wird nicht nur die richtige myprogram.exe.config-Datei generiert, sondern wenn Sie Setup and Deployment Project in Visual Studio verwenden, um MSI zu generieren, wird das Deployment-Projekt gezwungen, beim Paketieren die richtige Konfigurationsdatei zu verwenden.

6 Stimmen

Die ungeahnten Wunder von MSBuild. Jetzt frage ich mich, was noch alles möglich ist. Btw. dies funktioniert auch für clickonce Bereitstellungen direkt aus VS (im Gegensatz zu höher bewerteten Antworten).

5 Stimmen

Änderungen können mühsam und fehleranfällig werden, wenn die Configs viele Einträge enthalten, die für alle Builds gleich sind. Ich habe gerade mit einem Problem zu tun, bei dem in der .config einer Umgebung eine Änderung fehlte, und natürlich war es die Produktionsumgebung.

1 Stimmen

Zwei Kopien der Konfigurationsdatei zu haben, ist kein Problem, solange die Entwickler nicht diejenigen sind, die sie manuell pflegen.

39voto

bdeem Punkte 879

Inspiriert durch Oleg und andere in dieser Frage, habe ich die Lösung https://stackoverflow.com/a/5109530/2286801 einen Schritt weiter, um Folgendes zu ermöglichen.

  • Arbeitet mit ClickOnce
  • Arbeitet mit Setup- und Deployment-Projekten in VS 2010
  • Funktioniert mit VS2010, 2013, 2015 (habe 2012 nicht getestet, sollte aber auch funktionieren).
  • Funktioniert mit Team Build. (Sie müssen entweder A) Visual Studio oder B) Microsoft.Web.Publishing.targets und Microsoft.Web.Publishing.Tasks.dll installieren)

Diese Lösung funktioniert, indem die app.config-Transformation durchgeführt wird, bevor die app.config zum ersten Mal im MSBuild-Prozess referenziert wird. Sie verwendet eine externe Zieldatei, um die Verwaltung über mehrere Projekte hinweg zu erleichtern.

Anweisungen:

Ähnliche Schritte wie bei der anderen Lösung. Ich habe das, was gleich bleibt, zitiert und der Vollständigkeit halber und zum leichteren Vergleich aufgenommen.

0. Fügen Sie eine neue Datei mit dem Namen AppConfigTransformation.targets zu Ihrem Projekt hinzu

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <!-- Transform the app config per project configuration.-->
  <PropertyGroup>
    <!-- This ensures compatibility across multiple versions of Visual Studio when using a solution file.
         However, when using MSBuild directly you may need to override this property to 11.0 or 12.0 
         accordingly as part of the MSBuild script, ie /p:VisualStudioVersion=11.0;
         See http://blogs.msdn.com/b/webdev/archive/2012/08/22/visual-studio-project-compatability-and-visualstudioversion.aspx -->
    <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
  </PropertyGroup>

  <Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.targets" />

  <Target Name="SetTransformAppConfigDestination" BeforeTargets="PrepareForBuild" 
          Condition="exists('app.$(Configuration).config')">
    <PropertyGroup>
      <!-- Force build process to use the transformed configuration file from now on. -->
      <AppConfig>$(IntermediateOutputPath)$(TargetFileName).config</AppConfig>
    </PropertyGroup>
    <Message Text="AppConfig transformation destination: = $(AppConfig)" />
  </Target>

  <!-- Transform the app.config after the prepare for build completes. -->
  <Target Name="TransformAppConfig" AfterTargets="PrepareForBuild" Condition="exists('app.$(Configuration).config')">
    <!-- Generate transformed app config in the intermediate directory -->
    <TransformXml Source="app.config" Destination="$(AppConfig)" Transform="app.$(Configuration).config" />
  </Target>

</Project>

1. Fügen Sie dem Projekt eine XML-Datei für jede Konfiguration hinzu.

Normalerweise werden Sie Debug- und Release-Konfigurationen haben, also nennen Sie Ihre Dateien App.Debug.config und App.Release.config. In meinem Projekt habe ich eine Konfiguration für jede Art von Umgebung erstellt, so dass Sie vielleicht damit experimentieren möchten.

2. Projekt entladen und .csproj-Datei zur Bearbeitung öffnen

Visual Studio erlaubt es Ihnen, .csproj direkt im Editor zu bearbeiten - Sie müssen nur zuerst das Projekt entladen. Klicken Sie dann mit der rechten Maustaste darauf und wählen Sie Edit .csproj.

3. Binden Sie App.*.config-Dateien an die Haupt-App.config

Suchen Sie den Abschnitt der Projektdatei, der alle App.config- und App.*.config-Referenzen enthält, und ersetzen Sie sie wie folgt. Sie werden feststellen, dass wir None anstelle von Content verwenden.

<ItemGroup>
  <None Include="app.config"/>
  <None Include="app.Production.config">
    <DependentUpon>app.config</DependentUpon>
  </None>
  <None Include="app.QA.config">
    <DependentUpon>app.config</DependentUpon>
  </None>
  <None Include="app.Development.config">
    <DependentUpon>app.config</DependentUpon>
  </None>
</ItemGroup>

4. Aktivieren Sie die Transformationsmagie

Am Ende der Datei nach

<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

und vor dem Finale

</Project>

fügen Sie die folgende XML-Datei ein:

<Import Project="AppConfigTransformation.targets" />

Erledigt!

1 Stimmen

Versucht in VS Community 2015 RC und es ignoriert die app.Debug.config-Datei, die ich habe.

0 Stimmen

Ich erfolgreich verwendet die akzeptierte Antwort auf ein WinForms-Projekt .. aber aus irgendeinem rätselhaften Grund konnte nicht die akzeptierte ans. auf ein anderes WinForms-Projekt (alle in der gleichen Lösung) anwenden. Diese Antwort von @bdeem ist mein neuer Favorit - da sie korrekt mit meinem MSI-Projekt interagierte - vielen Dank!

0 Stimmen

Dies schien in VS 2015 nicht zu funktionieren. Ich habe die VisualStudioVersion von 10 auf 12 aktualisiert, aber keine Würfel. Irgendwelche Ideen?

35voto

jeroenh Punkte 25392

Meiner Erfahrung nach sind die Dinge, die ich umgebungsspezifisch machen muss, Dinge wie Verbindungszeichenfolgen, Anwendungseinstellungen und oft smpt-Einstellungen. Das Config-System erlaubt es, diese Dinge in separaten Dateien festzulegen. Sie können dies also in Ihrer app.config/web.config verwenden:

 <appSettings configSource="appsettings.config" />
 <connectionStrings configSource="connection.config" />
 <system.net>
    <mailSettings>
       <smtp configSource="smtp.config"/>
    </mailSettings>
 </system.net>

In der Regel lege ich diese konfigurationsspezifischen Abschnitte in separaten Dateien in einem Unterordner namens ConfigFiles ab (entweder im Stammverzeichnis der Projektmappe oder auf Projektebene, je nachdem). Ich definiere eine Datei pro Konfiguration, z.B. smtp.config.Debug und smtp.config.Release.

Dann können Sie ein Pre-Build-Ereignis wie folgt definieren:

copy $(ProjectDir)ConfigFiles\smtp.config.$(ConfigurationName) $(TargetDir)smtp.config

Bei der Entwicklung im Team können Sie dies weiter optimieren, indem Sie %COMPUTERNAME% und/oder %USERNAME% in die Konvention aufnehmen.

Das bedeutet natürlich, dass die Zieldateien (x.config) NICHT in die Versionskontrolle aufgenommen werden sollten (da sie generiert werden). Sie sollten sie dennoch zur Projektdatei hinzufügen und ihre Ausgabetyp-Eigenschaft auf "copy always" oder "copy if newer" setzen.

Es ist einfach, erweiterbar und funktioniert für alle Arten von Visual Studio-Projekten (Konsole, Winforms, WPF, Web).

0 Stimmen

Ich habe genau die gleiche Konfiguration wie Sie. Aber ich habe Probleme mit der Umwandlung der Smp-Datei. Können Sie das Original und die Umwandlung beifügen? Das sind meine: Die Basisdatei: <?xml version="1.0"?> <smtp deliveryMethod="SpecifiedPickupDirectory"> <specifiedPickupDirectory pickupDirectoryLocation="C:\mail"/> <network host="localhost"/> </smtp> Die Transformation: <?xml version="1.0"?> <smtp xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transfo‌​rm" xdt:Transform="Replace" from="user@email.com" deliveryMethod="Network"> <network .../> </smtp>

0 Stimmen

Ich bin nicht sicher, ob ich das verstehe. In dieser Konfiguration transformiere ich nichts, es werden nur Dateien kopiert...

0 Stimmen

Oh, ich habe den Teil mit der Kopie nicht gesehen. Ich habe die Konfiguration transformiert, anstatt sie einfach zu kopieren. Trotzdem vielen Dank.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X