Cara memilih app.config yang berbeda untuk beberapa konfigurasi build

115

Saya memiliki proyek tipe dll yang berisi tes integrasi MSTest. Pada mesin saya, tes lulus, dan saya ingin hal yang sama terjadi pada server CI (saya menggunakan TeamCity). Tetapi pengujian gagal, karena saya perlu mengubah beberapa pengaturan di app.config. Inilah mengapa saya berpikir untuk memiliki file app.config kedua yang terpisah yang akan menyimpan pengaturan untuk server CI.

Jadi saya ingin memilikinya

/ Sln
 / Proj
  app.config (Saya pikir ini diperlukan oleh VS)
  app.Release.config (Ini adalah file konfigurasi independen yang berdiri sendiri)

Jadi, jika saya memilih Konfigurasi rilis dalam konfigurasi build di CI, saya ingin menggunakan file app.Release.config daripada app.config

Masalah
Ini tampaknya tidak langsung untuk proyek tipe .dll sederhana. Untuk proyek web, saya dapat melakukan transformasi konfigurasi web. Saya menemukan peretasan bagaimana melakukan transformasi ini untuk proyek jenis dll, tetapi saya bukan penggemar peretasan.

Pertanyaan
Apa pendekatan standar untuk mengubah file app.config bergantung pada konfigurasi build untuk proyek .NET (seperti Debug, Rilis, ...)?

oleksii
sumber

Jawaban:

154

Gunakan plugin SlowCheetah . Untuk opsi dan detail selengkapnya tentang cara menggunakan SlowCheetah, teruslah membaca.

Seperti yang telah Anda perhatikan, tidak ada cara default dan mudah untuk menggunakan file konfigurasi yang berbeda untuk proyek tipe Library (.dll) . Alasannya adalah bahwa pemikiran saat ini adalah: "Anda tidak perlu"! Pengembang kerangka kerja menganggap Anda memerlukan konfigurasi untuk file yang dapat dieksekusi: baik itu konsol, desktop, web, aplikasi seluler, atau yang lainnya. Jika Anda mulai menyediakan konfigurasi untuk dll , Anda mungkin akan mendapatkan sesuatu yang saya sebut sebagai config hell . Anda mungkin tidak lagi memahami (dengan mudah) mengapa variabel ini dan itu memiliki nilai aneh yang muncul entah dari mana.

"Tunggu", - Anda mungkin berkata, "tetapi saya memerlukan ini untuk pengujian integrasi / unit saya, dan ini adalah perpustakaan!". Dan itu benar dan inilah yang dapat Anda lakukan (pilih hanya satu, jangan campur):

1. SlowCheetah - mengubah file konfigurasi saat ini

Anda dapat menginstal SlowCheetah - plug-in Visual Studio yang melakukan semua poking XML (atau transformasi) tingkat rendah untuk Anda. Cara kerjanya, secara singkat:

  • Instal SlowCheetah dan mulai ulang Visual Studio (Visual Studio> Tools> Extensions and Updates ...> Online> Visual Studio Gallery> cari "Slow Cheetah")
  • Tentukan konfigurasi solusi Anda ( Debug dan Rilis ada secara default), Anda dapat menambahkan lebih banyak (klik kanan pada solusi di Solution Explorer > Pengelola Konfigurasi ... > Konfigurasi Solusi Aktif > Baru ...
  • Tambahkan file konfigurasi jika perlu
  • Klik kanan pada file config> Add Transform
    • Ini akan membuat file Transformation - satu per konfigurasi Anda
    • File transformasi berfungsi sebagai injektor / mutator, mereka menemukan kode XML yang diperlukan dalam file konfigurasi asli dan memasukkan baris baru atau mengubah nilai yang diperlukan, apa pun yang Anda perintahkan.

2. Bermain-main dengan file .proj - salin-ganti nama file konfigurasi baru

Aslinya diambil dari sini . Ini adalah tugas MSBuild kustom yang dapat Anda sematkan ke dalam file Visual Studio .proj . Salin dan tempel kode berikut ke dalam file proyek

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

Sekarang buat folder dalam proyek yang disebut Configdan tambahkan file baru di sana: App.Debug.config , App.Release.config dan seterusnya. Sekarang, tergantung pada konfigurasi Anda, Visual Studio akan mengambil file konfigurasi dari Configfolder, dan menyalin-ganti namanya ke direktori output. Jadi jika Anda memiliki proyek PatternPA.Test.Integration dan konfigurasi Debug yang dipilih, di folder keluaran setelah pembuatan Anda akan menemukan file PatternPA.Test.Integration.dll.config yang disalin dari Config\App.Debug.configdan diganti namanya setelahnya.

Ini adalah beberapa catatan yang dapat Anda tinggalkan di file konfigurasi

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

Di Visual Studio Anda dapat memiliki sesuatu seperti ini

Struktur proyek

3. Gunakan file scripting di luar Visual Studio

Setiap alat pembangunan (seperti NAnt , MSBuild ) akan memberikan kemampuan untuk mengubah file konfigurasi tergantung pada konfigurasinya. Ini berguna jika Anda membangun solusi di mesin build, di mana Anda perlu memiliki kontrol lebih terhadap apa dan bagaimana Anda mempersiapkan produk untuk dirilis.

Misalnya Anda dapat menggunakan tugas dll penerbitan web untuk mengubah file konfigurasi apa pun

<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
sumber
Solusi kedua Anda berfungsi dengan baik, tetapi tidak untuk mempublikasikan proyek web. Setelah menerbitkan proyek ASP.NET, web.config asli diterbitkan.
Massood Khaari
3
@MassoodKhaari Anda perlu memastikan bahwa tugas ini dipanggil untuk target publikasi. Saat Anda memublikasikan proyek, target build terpisah akan dipanggil, yang mungkin tidak dipanggil secara default AfterBuild. Selama kompilasi biasa, AfterBuildtarget dipanggil secara default. Harus ada perbaikan cepat untuk mempublikasikan kasus
oleksii
1
Gunakan metode kedua Anda (agak). Pergi ke proyek properti dan mengedit BeforeBuild untuk menyalin App.<Target>.configselama App.configdi dir proyek , bukan output dir.
SparK
@oleksi Anda benar. Tetapi saya masih tidak dapat menemukan target yang digunakan proses penerbitan web saya (dalam Visual Studio 2013).
Massood Khaari
1
Saya menggunakan metode kedua, tetapi perlu menambahkan kondisi ke target AfterBuild untuk memastikan file benar-benar ada sebelum menghapus. Saya memiliki konfigurasi build Debug, yang pada dasarnya hanya menggunakan file App.config default, tetapi saya tidak memiliki App.Debug.config, yang berarti langkah build akan gagal. Saya baru saja menambahkan Condition="Exists('$(ProjectDir)App.$(Configuration).config')".
Siewers
23

Anda dapat mencoba pendekatan berikut:

  1. Klik kanan pada proyek di Solution Explorer dan pilih Unload Project .
  2. Proyek akan dibongkar. Klik kanan pada proyek itu lagi dan pilih Edit <YourProjectName> .csproj .
  3. Sekarang Anda dapat mengedit file proyek di dalam Visual Studio.
  4. Temukan tempat di file * .csproj tempat file konfigurasi aplikasi Anda disertakan. Ini akan terlihat seperti:
    <ItemGroup>
        <None Include = "App.config" />
    </ItemGroup>
  1. Ganti baris ini dengan yang berikut:
    <ItemGroup Condition = "'$ (Configuration)' == 'Debug'">
        <None Include = "App.Debug.config" />
    </ItemGroup>

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

Saya belum mencoba pendekatan ini ke app.configfile, tetapi berfungsi dengan baik dengan item lain dari proyek Visual Studio. Anda dapat menyesuaikan proses build dengan hampir semua cara yang Anda suka. Bagaimanapun, beri tahu saya hasilnya.

vharavy
sumber
Tnx untuk jawabannya, tetapi ini tidak berfungsi dengan app.config. VS membutuhkan sebuah wajib app.configdan tidak menerapkan konfigurasi Rilis jika saya menggunakan VS build atau Teamcity VS sln build runner.
oleksii
2
Di sini menjelaskan cara melakukannya: Aktifkan app.debug.config app.release.config
Gabrielizalo
1
Mengapa jawaban ini mendapat banyak suara? Saya mencobanya dan tidak berhasil. Faktanya, baik dalam mode debug dan rilis tidak ada file App.config dan oleh karena itu, tidak ada file yang sesuai di folder keluaran. File App.Debug.config dan App.Release.config tidak memiliki arti apa pun untuk Visual Studio.
MarkusParker
Tidak bekerja: .csproj tidak dapat dibuka, pesan kesalahan "elemen di luar elemen Target harus memiliki: Sertakan, Perbarui atau Hapus"
Elo
12

Anda harus mempertimbangkan ConfigGen . Ini dikembangkan untuk tujuan ini. Ini menghasilkan file konfigurasi untuk setiap mesin penyebaran, berdasarkan file template dan file pengaturan. Saya tahu bahwa ini tidak menjawab pertanyaan Anda secara spesifik, tetapi mungkin menjawab masalah Anda dengan baik.

Jadi daripada Debug, Rilis dll, Anda mungkin memiliki Tes, UAT, Produksi dll. Anda juga dapat memiliki pengaturan yang berbeda untuk setiap mesin pengembang, sehingga Anda dapat membuat konfigurasi khusus untuk mesin dev Anda dan mengubahnya tanpa memengaruhi penerapan orang lain .

Contoh penggunaan mungkin ...

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

Jika Anda menempatkan ini di file .csproj Anda, dan Anda memiliki file berikut ...

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

... maka ini akan menjadi hasilnya ...

Dari perintah pertama, file konfigurasi dibuat untuk setiap lingkungan yang ditentukan dalam file xls, ditempatkan di direktori keluaran $ (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>

Dari perintah kedua, App.config lokal yang digunakan pada mesin dev Anda akan diganti dengan konfigurasi yang dihasilkan yang ditentukan oleh sakelar lokal (-l) dan sakelar nama file (-n).

Daniel Dyson
sumber
2
Tnx untuk jawabannya, ini terlihat lumayan. Tetapi ada beberapa kekurangan, ini hanya menunjukkan 75 unduhan (jadi tidak matang) dan hanya berfungsi dengan .xls atau .xlsx. Saya tidak benar-benar ingin bergantung pada format dokumen kustom lain untuk operasi sederhana. Saya mencari pendekatan yang lebih standar ...
oleksii
2
Poin yang adil, meskipun dikatakan 194 unduhan di CodePlex, xls adalah spreadsheet, bukan format khusus, dan saya tahu tiga Bank Investasi Utama yang telah menyetujui ini untuk digunakan, jadi jika itu cukup baik untuk mereka ... Juga, satu fitur yang saat ini diminta adalah menggunakan xml untuk pengaturannya. Ini hampir siap, tetapi saya lebih suka pendekatan spreadsheet. Jauh lebih mudah untuk melihat setiap pengaturan untuk setiap lingkungan dalam tampilan tabel
Daniel Dyson
Kami sekarang berada di tahap akhir pengujian versi configGen yang dapat digunakan untuk menghasilkan file teks biasa, bukan hanya xml. Jadi, jika Anda ingin membuat css, sql, javascript, dll. Untuk lingkungan khusus, perhatikan situs configGen
Daniel Dyson
terima kasih Daniel untuk solusinya, inilah yang saya cari. Saya akan mencobanya.
Bhupinder Singh
10

Menggunakan pendekatan yang sama seperti Romeo, saya menyesuaikannya dengan Visual Studio 2010:

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

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

Di sini Anda perlu menyimpan kedua file App.config di direktori yang berbeda (appDebug dan appRelease). Saya mengujinya dan berfungsi dengan baik!

tem peru
sumber
3

Saya menggunakan alat XmlPreprocess untuk manipulasi file konfigurasi. Ini menggunakan satu file pemetaan untuk beberapa lingkungan (atau beberapa target build dalam kasus Anda). Anda dapat mengedit file pemetaan dengan Excel. Sangat mudah digunakan.

Ludwo
sumber
3

SlowCheetah dan FastKoala dari Galeri VisualStudio tampaknya menjadi alat yang sangat bagus yang membantu mengatasi masalah ini.

Namun, jika Anda ingin menghindari addins atau menggunakan prinsip-prinsip yang mereka terapkan secara lebih luas selama proses build / integrasi, maka menambahkan ini ke file msbuild * proj Anda adalah perbaikan singkat.

Note: ini kurang lebih merupakan pengerjaan ulang dari jawaban @ oleksii no. 2.

Ini berfungsi untuk proyek .exe dan .dll:

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

Ini berfungsi untuk proyek web:

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

Perhatikan bahwa langkah ini terjadi bahkan sebelum build yang tepat dimulai. Transformasi file konfigurasi terjadi di folder proyek. Sehingga web.config yang telah diubah tersedia saat Anda melakukan debug (kekurangan dari SlowCheetah).

Ingatlah bahwa jika Anda membuat folder App_Config (atau apa pun yang Anda pilih untuk menyebutnya), berbagai file konfigurasi perantara harus memiliki Build Action = None, dan Copy to Output Directory = Jangan salin.

Ini menggabungkan kedua opsi menjadi satu blok. Yang sesuai dijalankan berdasarkan kondisi. Tugas TransformXml didefinisikan terlebih dahulu:

<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
sumber
Saya baru saja mencoba ini di Visual Studio 2017 dan tidak berhasil. Menembak. Saya benar-benar berharap ini akan berhasil, karena sepertinya yang paling mudah untuk diterapkan.
Greg Burghardt
Tugas TransformXml tidak ditentukan dalam sampel. Saya menambahkan entri. Anda dapat menentukannya di file mycustom.t target yang disertakan dalam semua proyek peluncuran dalam solusi Anda.
Eniola
@GregBurghardt, mau coba sekarang?
Eniola
Saya mungkin akan mencobanya. Saya menginstal plugin Config Transform untuk Visual Studio, dan itu bekerja dengan sangat baik. Saya sebenarnya bertanya-tanya apakah plugin pada dasarnya melakukan apa yang dilakukan jawaban Anda.
Greg Burghardt
Oke, beri tahu saya bagaimana kelanjutannya.
Eniola
1

Lihat apakah mesin transformasi XDT (web.config) dapat membantu Anda. Saat ini hanya didukung secara native untuk proyek web, tetapi secara teknis tidak ada yang menghentikan Anda untuk menggunakannya di jenis aplikasi lain. Ada banyak panduan tentang cara menggunakan XDT dengan mengedit file proyek secara manual, tetapi saya menemukan plugin yang berfungsi dengan baik: https://visualstudiogallery.msdn.microsoft.com/579d3a78-3bdd-497c-bc21-aa6e6abbc859

Plugin hanya membantu menyiapkan konfigurasi, tidak perlu membangun dan solusinya dapat dibangun di mesin lain atau di server build tanpa plugin atau alat lain yang diperlukan.

TGasdf
sumber
Ini harus menjadi jawabannya sekarang. Baru saja mencobanya di VS 2017 dan itu bekerja seperti pesona. Anda tidak perlu menerbitkan proyek. Bangun saja. Berfungsi sangat baik untuk proyek pengujian kami untuk digunakan dalam build integrasi berkelanjutan sehingga kami dapat menjalankan pengujian Selenium dalam mode tanpa kepala, namun secara lokal pengujian tersebut berjalan dengan browser terbuka. +1.000.000 jika saya bisa.
Greg Burghardt
1

Saya telah memecahkan topik ini dengan solusi yang saya temukan di sini: http://www.blackwasp.co.uk/SwitchConfig.aspx

Singkatnya apa yang mereka nyatakan di sana adalah: "dengan menambahkan acara pasca-pembangunan. [...] Kita perlu menambahkan yang berikut ini:

if "Debug"=="$(ConfigurationName)" goto :nocopy
del "$(TargetPath).config"
copy "$(ProjectDir)\Release.config" "$(TargetPath).config"
:nocopy
Janbro
sumber
Sejauh ini, metode termudah untuk melakukan apa yang seharusnya menjadi fungsi yang sangat sederhana dan esensial yang dikacaukan oleh pemikir berlebihan! Terima kasih Janbro.
BoiseBaked
1

Saya telah mendengar hal-hal baik tentang SlowCheetah, tetapi tidak dapat membuatnya berfungsi. Saya melakukan hal berikut: tambahkan tag am ke masing-masing untuk konfigurasi tertentu.

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
sumber
Ini sepertinya cara super sederhana lainnya untuk mengubah file app.config sesuai dengan konfigurasi build. Mike, apakah Anda menguji dengan Debug dan Konfigurasi Rilis standar?
BoiseBaked
0

Setelah beberapa penelitian tentang mengelola konfigurasi untuk pengembangan dan membangun dll, saya memutuskan untuk membuat sendiri, saya telah membuatnya tersedia di bitbucket di: https://bitbucket.org/brightertools/contemplate/wiki/Home

Ini beberapa file konfigurasi untuk berbagai lingkungan, ini adalah alat pengganti entri konfigurasi dasar yang akan bekerja dengan format file berbasis teks.

Semoga ini membantu.

Mark Redman
sumber