Jak wybrać inny plik app.config dla kilku konfiguracji kompilacji

115

Mam projekt typu dll, który zawiera testy integracji MSTest. Na moim komputerze testy kończą się pomyślnie i chcę, aby to samo działo się na serwerze CI (używam TeamCity). Ale testy kończą się niepowodzeniem, ponieważ muszę dostosować niektóre ustawienia w app.config. Dlatego myślałem o oddzielnym drugim pliku app.config, który będzie zawierał ustawienia serwera CI.

Więc chciałbym mieć

/ Sln
 / Proj
  app.config (myślę, że jest to wymagane przez VS)
  app.Release.config (jest to samodzielny niezależny plik konfiguracyjny)

Dlatego jeśli wybiorę konfigurację wydania w konfiguracji kompilacji na CI, chciałbym użyć pliku app.Release.config zamiast app.config

Problem
Nie wydaje się to być proste w przypadku prostych projektów typu .dll. W przypadku projektów internetowych mogę dokonać transformacji konfiguracji sieciowej. Znalazłem hack, jak wykonać te transformacje dla projektu typu dll, ale nie jestem wielkim fanem hacków.

Pytanie
Jakie jest standardowe podejście do dostosowywania plików app.config w zależności od konfiguracji kompilacji dla projektów .NET (takich jak debugowanie, wydanie, ...)?

oleksii
źródło

Odpowiedzi:

154

Użyj wtyczki SlowCheetah . Aby uzyskać więcej opcji i szczegółów dotyczących korzystania ze SlowCheetah, czytaj dalej.

Jak już zauważyłeś, nie ma domyślnego i łatwego sposobu na użycie różnych plików konfiguracyjnych dla projektu typu Biblioteka (.dll) . Powodem jest to, że obecne myślenie brzmi: „Nie musisz”! Twórcy frameworka uważają, że potrzebujesz konfiguracji dla pliku wykonywalnego: czy to konsoli, komputera stacjonarnego, aplikacji internetowej, aplikacji mobilnej czy czegoś innego. Jeśli zaczniesz konfigurować bibliotekę dll , możesz skończyć z czymś, co mogę nazwać piekłem konfiguracji . Możesz już nie rozumieć (łatwo), dlaczego zmienne te i te mają tak dziwne wartości, które pojawiają się znikąd.

„Zaczekaj” - możesz powiedzieć, „ale potrzebuję tego do mojej integracji / testów jednostkowych, a to jest biblioteka!”. I to prawda i oto, co możesz zrobić (wybierz tylko jeden, nie mieszaj):

1. SlowCheetah - przekształca aktualny plik konfiguracyjny

Możesz zainstalować SlowCheetah - wtyczkę Visual Studio, która wykona za Ciebie wszystkie niskopoziomowe kodowanie XML (lub transformację). Sposób działania, pokrótce:

  • Zainstaluj SlowCheetah i uruchom ponownie program Visual Studio (Visual Studio> Narzędzia> Rozszerzenia i aktualizacje ...> Online> Visual Studio Gallery> wyszukaj „Slow Cheetah”)
  • Zdefiniuj konfiguracje rozwiązania ( debugowanie i wydanie są dostępne domyślnie), możesz dodać więcej (kliknij prawym przyciskiem myszy rozwiązanie w Eksploratorze rozwiązań > Configuration Manager ... > Konfiguracja aktywnego rozwiązania > Nowy ...
  • W razie potrzeby dodaj plik konfiguracyjny
  • Kliknij prawym przyciskiem myszy plik konfiguracyjny> Dodaj transformację
    • Spowoduje to utworzenie plików transformacji - po jednym dla każdej konfiguracji
    • Pliki transformacji działają jako wtryskiwacze / mutatory, znajdują potrzebny kod XML w oryginalnym pliku konfiguracyjnym i wstrzykują nowe wiersze lub modyfikują wymaganą wartość, cokolwiek mu powiesz

2. Baw się z plikiem .proj - kopiuj i zmieniaj nazwę zupełnie nowego pliku konfiguracyjnego

Pierwotnie wzięty stąd . Jest to niestandardowe zadanie programu MSBuild, które można osadzić w pliku .proj programu Visual Studio . Skopiuj i wklej następujący kod do pliku projektu

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

Teraz utwórz folder w projekcie o nazwie Configi dodaj tam nowe pliki: App.Debug.config , App.Release.config i tak dalej. Teraz, w zależności od konfiguracji, program Visual Studio wybierze plik konfiguracyjny z Configfolderu i skopiuje go i zmień jego nazwę do katalogu wyjściowego. Więc jeśli masz projekt PatternPA.Test.Integration i wybraną konfigurację Debug , w folderze wyjściowym po kompilacji znajdziesz plik PatternPA.Test.Integration.dll.config , który został skopiowany Config\App.Debug.configi zmieniony później.

Oto kilka uwag, które możesz zostawić w plikach konfiguracyjnych

<?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>

W Visual Studio możesz mieć coś takiego

Struktura projektu

3. Używaj plików skryptów poza programem Visual Studio

Każde narzędzie do kompilacji (takie jak NAnt , MSBuild ) zapewni możliwości przekształcania pliku konfiguracyjnego w zależności od konfiguracji. Jest to przydatne, jeśli tworzysz rozwiązanie na maszynie do kompilacji, na której musisz mieć większą kontrolę nad tym, co i jak przygotowujesz produkt do wydania.

Na przykład możesz użyć zadania dll publikowania w sieci Web, aby przekształcić dowolny plik konfiguracyjny

<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
źródło
Twoje drugie rozwiązanie działa dobrze, ale nie do publikowania projektów internetowych. Po opublikowaniu projektu ASP.NET publikowany jest oryginalny plik web.config.
Massood Khaari,
3
@MassoodKhaari musisz upewnić się, że to zadanie jest wywoływane dla celu publikacji. Podczas publikowania projektu wywoływany jest oddzielny cel kompilacji, który może nie wywoływać domyślnego AfterBuildcelu. Podczas typowej kompilacji AfterBuildcel jest wywoływany domyślnie. Powinno być szybkie rozwiązanie dla przypadku publikacji
oleksii
1
Użyłeś swojej drugiej metody (trochę). Udał się do właściwości projektu i redagował BeforeBuild aby skopiować App.<Target>.confignad App.configw katalogu projektu , a nie dir wyjściowego.
SparK
@oleksii Masz rację. Ale nadal nie mogłem znaleźć celu, z którego korzysta mój proces publikowania w sieci Web (w programie Visual Studio 2013).
Massood Khaari
1
Używam drugiej metody, ale przed usunięciem potrzebowałem dodać warunek do celu AfterBuild, aby upewnić się, że plik faktycznie istnieje. Mam konfigurację kompilacji debugowania, która po prostu używa domyślnego pliku App.config, ale nie miałem pliku App.Debug.config, co oznaczało, że krok kompilacji się nie powiedzie. Właśnie dodałem Condition="Exists('$(ProjectDir)App.$(Configuration).config')".
Siewers
23

Możesz wypróbować następujące podejście:

  1. Kliknij prawym przyciskiem myszy projekt w Eksploratorze rozwiązań i wybierz Zwolnij projekt .
  2. Projekt zostanie rozładowany. Ponownie kliknij projekt prawym przyciskiem myszy i wybierz Edytuj <YourProjectName> .csproj .
  3. Teraz możesz edytować plik projektu w programie Visual Studio.
  4. Znajdź miejsce w pliku * .csproj, w którym znajduje się plik konfiguracyjny aplikacji. Będzie wyglądać następująco:
    <ItemGroup>
        <None Include = "App.config" />
    </ItemGroup>
  1. Zastąp te wiersze następującymi:
    <ItemGroup Condition = "'$ (Configuration)' == 'Debug'">
        <None Include = "App.Debug.config" />
    </ItemGroup>

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

Nie próbowałem tego podejścia do app.configplików, ale działało dobrze z innymi elementami projektów Visual Studio. Możesz dostosować proces budowania w prawie dowolny sposób. W każdym razie daj mi znać wynik.

vharavy
źródło
Tnx na odpowiedź, ale to nie działa z app.config. VS wymaga obowiązkowej app.configi nie stosuje konfiguracji wydania, jeśli używam kompilacji VS lub narzędzia do uruchamiania kompilacji Teamcity VS sln.
oleksii
2
Tutaj wyjaśniono, jak to zrobić: Włącz app.debug.config app.release.config
Gabrielizalo
1
Dlaczego ta odpowiedź ma tak wiele głosów pozytywnych? Spróbowałem i nie działa. W rzeczywistości zarówno w trybie debugowania, jak i zwolnienia nie ma pliku App.config, a zatem w folderze wyjściowym nie ma odpowiedniego pliku. Pliki App.Debug.config i App.Release.config nie mają żadnego znaczenia dla programu Visual Studio.
MarkusParker
To nie działa: .csproj nie może zostać otwarty, komunikat o błędzie „Elementy spoza elementów docelowych muszą mieć: Uwzględnij, zaktualizuj lub usuń”
Elo
12

Powinieneś rozważyć ConfigGen . Został opracowany w tym celu. Tworzy plik konfiguracyjny dla każdej maszyny wdrożeniowej na podstawie pliku szablonu i pliku ustawień. Wiem, że to nie odpowiada konkretnie na twoje pytanie, ale może dobrze odpowiedzieć na twój problem.

Więc zamiast debugowania, wydania itp. Możesz mieć test, UAT, produkcję itp. Możesz także mieć różne ustawienia dla każdej maszyny deweloperskiej, abyś mógł wygenerować konfigurację specyficzną dla swojej maszyny deweloperskiej i zmienić ją bez wpływu na wdrożenie kogokolwiek innego .

Przykładem użycia może być ...

<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>

Jeśli umieścisz to w swoim pliku .csproj i masz następujące pliki ...

$(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>

... to będzie wynik ...

Od pierwszego polecenia, plik konfiguracyjny wygenerowany dla każdego środowiska określonego w pliku xls, umieszczony w katalogu wyjściowym $ (SolutionDir) ConfigGen

.../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>

Od drugiego polecenia lokalny plik App.config używany na maszynie deweloperskiej zostanie zastąpiony wygenerowaną konfiguracją określoną przez przełącznik lokalny (-l) i przełącznik nazwy pliku (-n).

Daniel Dyson
źródło
2
Tnx za odpowiedź, to nie wygląda źle. Ale są pewne wady, pokazuje tylko 75 pobrań (więc nie jest dojrzały) i działa tylko z .xls lub .xlsx. Naprawdę nie chcę polegać na jeszcze jednym niestandardowym formacie dokumentu w zakresie prostych operacji. Szukałem bardziej standardowego podejścia ...
oleksii
2
Słuszna uwaga, chociaż na CodePlex jest napisane 194 pliki do pobrania, xls to arkusz kalkulacyjny, raczej nie niestandardowy format, i znam trzy główne banki inwestycyjne, które zatwierdziły to do użytku, więc jeśli jest dla nich wystarczająco dobre ... Ponadto jeden z aktualnie żądanych funkcji jest użycie XML dla ustawień. Jest już prawie gotowe, ale i tak wolę podejście oparte na arkuszu kalkulacyjnym. O wiele łatwiej jest zobaczyć każde ustawienie dla każdego środowiska w widoku tabelarycznym
Daniel Dyson,
Jesteśmy teraz na końcowych etapach testowania wersji configGen, której można użyć do generowania zwykłych plików tekstowych, a nie tylko XML. Więc jeśli chcesz wygenerować specyficzne dla środowiska css, sql, javascript itp., Miej oko na stronę configGen
Daniel Dyson
dzięki Daniel za rozwiązanie, właśnie tego szukałem. Spróbuję.
Bhupinder Singh
10

Korzystając z tego samego podejścia co Romeo, dostosowałem go do Visual Studio 2010:

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

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

Tutaj musisz przechowywać oba pliki App.config w różnych katalogach (appDebug i appRelease). Przetestowałem to i działa dobrze!

tem peru
źródło
3

Używam narzędzie XmlPreprocess dla plikach konfiguracyjnych manipulacji. Używa jednego pliku mapowania dla wielu środowisk (lub wielu obiektów docelowych kompilacji w twoim przypadku). Możesz edytować plik mapowania w programie Excel. Jest bardzo łatwy w użyciu.

Ludwo
źródło
3

SlowCheetah i FastKoala z Galerii VisualStudio wydają się być bardzo dobrymi narzędziami, które pomagają rozwiązać ten problem.

Jeśli jednak chcesz uniknąć dodatków lub korzystać z zasad, które implementują one szerzej w procesach kompilacji / integracji, dodanie tego do plików msbuild * proj jest skróconą poprawką.

Uwaga: jest to mniej więcej przeróbka odpowiedzi nr 2 z @ oleksii.

Działa to w przypadku projektów .exe i .dll:

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

Działa to w przypadku projektów internetowych:

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

Zauważ, że ten krok ma miejsce nawet przed rozpoczęciem właściwej kompilacji. Transformacja pliku konfiguracyjnego odbywa się w folderze projektu. Aby przekształcony plik web.config był dostępny podczas debugowania (wada SlowCheetah).

Pamiętaj, że jeśli utworzysz folder App_Config (lub cokolwiek wybierzesz), różne pośrednie pliki konfiguracyjne powinny mieć Akcję kompilacji = Brak i Kopiuj do katalogu wyjściowego = Nie kopiuj.

Łączy obie opcje w jeden blok. Odpowiedni jest wykonywany na podstawie warunków. Jednak zadanie TransformXml jest definiowane jako pierwsze:

<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
źródło
Właśnie wypróbowałem to w programie Visual Studio 2017 i nie działa. Strzelać. Naprawdę miałem nadzieję, że to zadziała, ponieważ wygląda na najłatwiejsze do wdrożenia.
Greg Burghardt
Zadanie TransformXml nie jest zdefiniowane w przykładach. Dodaję wpis. Możesz to zdefiniować w pliku mycustom.targets, który zostanie dołączony do wszystkich projektów uruchamiania w Twoim rozwiązaniu.
Eniola
@GregBurghardt, czy chcesz teraz spróbować?
Eniola
Mogę spróbować. Zainstalowałem wtyczkę Config Transform dla Visual Studio i działała naprawdę dobrze. Właściwie zastanawiam się, czy wtyczka zasadniczo robi to, co robi twoja odpowiedź.
Greg Burghardt
OK, daj mi znać, jak leci.
Eniola
1

Sprawdź, czy silnik transformacji XDT (web.config) może Ci pomóc. Obecnie jest natywnie obsługiwany tylko w projektach internetowych, ale technicznie nic nie stoi na przeszkodzie, abyś używał go w innych typach aplikacji. Istnieje wiele przewodników na temat korzystania z XDT przez ręczną edycję plików projektu, ale znalazłem wtyczkę, która działa świetnie: https://visualstudiogallery.msdn.microsoft.com/579d3a78-3bdd-497c-bc21-aa6e6abbc859

Wtyczka pomaga tylko w konfiguracji konfiguracji, nie jest potrzebna do budowania, a rozwiązanie można zbudować na innych maszynach lub na serwerze kompilacji bez wtyczki lub innych narzędzi.

TGasdf
źródło
To powinna być teraz odpowiedź. Właśnie wypróbowałem to na VS 2017 i działa jak urok. Nie musisz publikować projektu. Po prostu to zbuduj. Działa świetnie w naszym projekcie testowym do wykorzystania w naszej kompilacji ciągłej integracji, dzięki czemu możemy uruchamiać testy Selenium w trybie bezgłowym, ale lokalnie działają one z otwieraną przeglądarką. +1 000 000, gdybym mógł.
Greg Burghardt
1

Rozwiązałem ten temat za pomocą rozwiązania, które znalazłem tutaj: http://www.blackwasp.co.uk/SwitchConfig.aspx

Krótko mówiąc, stwierdzają: „przez dodanie zdarzenia po kompilacji. […] Musimy dodać, co następuje:

if "Debug"=="$(ConfigurationName)" goto :nocopy
del "$(TargetPath).config"
copy "$(ProjectDir)\Release.config" "$(TargetPath).config"
:nocopy
Janbro
źródło
Zdecydowanie najłatwiejsza metoda zrobienia czegoś, co powinno być bardzo prostą i podstawową funkcją, która została schrzaniona przez nadmiernie myślących! Dzięki Janbro.
BoiseBaked
1

Słyszałem dobre rzeczy o SlowCheetah, ale nie mogłem go uruchomić. Wykonałem następujące czynności: dodałem tag do każdego z nich dla określonej konfiguracji.

Dawny:

<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>
Mikrofon
źródło
Wydaje się, że jest to kolejny super prosty sposób zmiany plików app.config zgodnie z konfiguracją kompilacji. Mike, czy testowałeś ze standardowymi konfiguracjami debugowania i wydania?
BoiseBaked
0

Po kilku badaniach dotyczących zarządzania konfiguracjami dla rozwoju i kompilacji itp., Zdecydowałem się stworzyć własną, udostępniłem ją na bitbucket pod adresem : https://bitbucket.org/brightertools/contemplate/wiki/Home

To wiele plików konfiguracyjnych dla wielu środowisk, jest to podstawowe narzędzie zastępujące wpisy konfiguracji, które będzie działać z dowolnym formatem plików tekstowych.

Mam nadzieję że to pomoże.

Mark Redman
źródło