タイトル通りのことをやりたかったけど、思ったより苦労したのでそのメモ。
Visual Studio 2017
失敗:ASP.NETのApp.configを切り替える機能を使う
ASP.NETではビルド構成に合わせてApp.configを切り替える機能があるが、Windows Formにはない。
検索すると、WindowsアプリでもASP.NETの機能を流用してconfigファイルを置き換える手段が見つかる。
App.configをビルドターゲットによって書き換える - Qiita
しかし、実際にやってみてもビルド後のconfigファイルが置き換わらない。
<appSettings>
タグも「設定」関連のどちらも置き換わらず。
Settingsファイルを2つ作り、ビルド時に構成によって切り替えようとしたけど、それもダメだった。
<None Include="Settings.Debug.settings" Condition=" '$(Configuration)' == 'Debug' ">
<Generator>SettingsSingleFileGenerator</Generator>
</None>
<None Include="Settings.Release.settings" Condition=" '$(Configuration)' == 'Release' ">
<Generator>SettingsSingleFileGenerator</Generator>
</None>
condition属性が有効にならないし、ファイル名=クラス名になってしまうので置換になっていない。
プロジェクト直下にDebugとReleaseのフォルダを作成し、同じSettings1.settingsというファイルを作ってみたところ、お互いが競合してapp.configとsettingsファイルを上書きしあってしまう。
ビルド後スクリプトでconfigファイルの内容を置き換える
Visual Studioには、ビルド前、ビルド後に実行させたいことを指定できる。
方法: ビルド イベントを指定する (Visual Basic) - Visual Studio | Microsoft Docs
これを使い、ビルド後にconfigファイルを置き換える処理を自作した。
configファイルを用意する
オリジナルのApp.configと構成毎のconfigファイルを用意する。
3つ並ぶのが鬱陶しいなら、vbprojファイルをいじって、以下のようにできる。
<Content Include="App.config">
<SubType>Designer</SubType>
</Content>
<Content Include="App.Debug.config">
<DependentUpon>App.config</DependentUpon>
<SubType>Designer</SubType>
</Content>
<Content Include="App.Release.config" >
<DependentUpon>App.config</DependentUpon>
<SubType>Designer</SubType>
</Content>
PowerShellでconfigファイルの内容を上書きする
.NETにはconfigファイルを読み書きするためのクラス等が用意されているが、「設定」の部分は扱えないようなので、普通のXMLファイルとして読み書きする。
↓appSettings
タグしか使用しないなら有用な方法。
PowerShellでアプリケーション構成ファイル(app.config)を読み書きする - しばたテックブログ
App.configをXMLファイルとして読み取り、以下で囲んだ部分を読み取って置き換える。
PowerShellに渡すパラメータとして、以下が必要:
- オリジナルのApp.configのファイルパス
- 置き換えたい内容が含まれているApp.configのファイルパス(App.Debug.configなど)
- プロジェクト名 (MySettingsが定義されているタグ名にプロジェクト名が入っている)
Param($targetAppConfigPath, $sourceAppConfigPath, $outputPath, $projectName)
Add-Type -AssemblyName System.Configuration
if (!(Test-Path $targetAppConfigPath) -or !(Test-Path $sourceAppConfigPath)) {
return
}
# ファイル読込
[xml]$targetAppConfig = Get-Content $targetAppConfigPath -Encoding UTF8
[xml]$sourceAppConfig = Get-Content $sourceAppConfigPath -Encoding UTF8
function main() {
copySettings "configuration/applicationSettings/$projectName.My.MySettings"
copySettings "configuration/userSettings/$projectName.My.MySettings"
copyConnectionStrings "configuration/connectionStrings"
copyAppConfigs "configuration/appSettings"
$targetAppConfig.Save($outputPath)
}
PowerShellをプロジェクトに配置する
プロジェクト内にps1ファイルを置く。サンプルでは「BuildScripts」フォルダに置いた。
PowerShellをビルド後に実行する
プロジェクトのプロパティを開き、「コンパイル」タブの「ビルドイベント」を押す。
以下のコマンドを、ビルド後のコマンドに追加する。
powershell -NoProfile -ExecutionPolicy Unrestricted -file "$(ProjectDir)BuildScripts\ReplaceSettings.ps1" "$(ProjectDir)App.config" "$(ProjectDir)App.$(ConfigurationName).config" "$(TargetDir)$(TargetFileName).config" $(ProjectName)
通常、PowerShellを呼び出すときに-file
は無くても良いはずだが、ここでは付けないとエラーになる。
これで、出力フォルダには構成毎の設定値が出力されるようになる。
このスクリプトを使ったサンプルをGitHubに保管した。
https://github.com/vicugna-pacos/vbnet_separate_config