今日はDLLのバージョンごとのコンパイルを自動化する方法を紹介します。
ぼくが今回なぜこのようなことを望んだのかというと、
過去に「Oracel.DataAccess.dll」という、Oracleクライアント用DLLを組み込む際に、納め先ごとにOracleのバージョンが異なる要件がありました。
一度きりであれば、「IDE上で参照設定を変えてビルド」でも良いのですが、修正&リリースのたびにはやってられまてん。
と、いうわけでDLLのバージョンごとにビルドしてくれるPowerShellスクリプトを作ります。
Visual Studio上でビルドをすると、内部で何をしているか。
現在のプロジェクトファイル(.csproj)に対して、MSBuildコマンドを実行してコンパイルしているのですね。
これを頭に入れると答えは出てきます。
処理手順は↓のイメージです。
DLLの用意以外はバッチにやらせます。
それでは実際に作っていきます。
ここではOracle.DataAccessを↓のバージョンごとにコンパイルする想定で行います。
異なるバージョンでもDLLの名前は同じほうが都合が良いので、フォルダをわけます。
フォルダ名は↓のようにバージョンにします。
(プロジェクトルート) ┃ プロジェクトファイル(example.csproj) ┃ build.ps1 ┃ : ┗ DLL ┗ 4.112.3.0 ┗ Oracle.DataAccess.dll ┗ 4.122.1.0 ┗ Oracle.DataAccess.dll ┗ 10.2.0.200 ┗ Oracle.DataAccess.dll
DLLの数分プロジェクトファイルを作成し、MSBuildを実行するスクリプトです。
build.ps1
# カレントディレクトリをスクリプト自身のパスに移動
$scriptPath = $MyInvocation.MyCommand.Path
$scriptDirPath = Split-Path -Parent $scriptPath
cd $scriptDirPath;
# 「DLL」フォルダ直下のフォルダ名を取得
$targets = Get-ChildItem DLL -Name
# 取得したフォルダ数(バージョン数)分ループ
foreach($target in $targets) {
# ベースのプロジェクトファイルからコピーする "{プロジェクト名}_{バージョン}.csproj"
$fileName_dest = "example_" + $target + ".csproj"
Copy-Item example.csproj $fileName_dest
# ファイルから読み込んだ文字列を格納
$data = Get-Content $fileName_dest
# "Oracle.DataAccess"を含む行番号を取得
$condition = "Oracle.DataAccess.dll"
$rowNum = Select-String $condition $fileName_dest | ForEach-Object { $($_ -split":")[2]}
# DLLのパスを置き換える
$data[$rowNum - 1] = " DLL\" + $target + "\Oracle.DataAccess.dll "
# ファイルへ出力
$data | Out-File -Encoding UTF8 $fileName_dest
# MSBuildの実行 TODO:Frameworkのパスは適宜変更
C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe $fileName_dest /t:Rebuild /p:"PostBuildEvent=;PlatformTarget=x64;OutputPath=bin\$target"
# 複製したプロジェクトファイルの削除
Remove-Item $fileName_dest
}
VisualStudioでビルドした際に実行してほしいので、プロジェクトのプロパティ – ビルド後イベントに↓を指定します。
powershell -ExecutionPolicy RemoteSigned -File "$(ProjectDir)build.ps1"
PowerShell上で、「PostBuildEvent=;」としたのは、上記で設定したビルド後のイベントが無限ループしてしまうのを防ぐためです。
IDE上でビルドを実行します。そうすると、
プロジェクトフォルダ – bin直下に↓のフォルダができたはずです。
中身はビルドしたアッセンブリがいるはずです。
以上、バージョンごとのビルドを自動化する方法でした。