[.NET] C# プロジェクトが使用する中間ファイル フォルダ (obj) を切り替える

昔はそうじゃなかった気がするんだが、VS2008, VS2010 の C# プロジェクトでは、設定画面に中間ファイルの作成先が無い。でも、.NET Framework のビルドルールでは、中間ファイルに対して操作を行うところが少なからずあるので、中間ファイルのフォルダが複数のプロジェクトで重複しているとヤバイ挙動をすることがある。
具体的にいうと、ClickOnce のバージョンチェックなんかが該当し、アプリケーションマニュフェストや配置マニュフェストが不正な内容になってしまったりする。

これを防ぐためには、プロジェクト毎に中間ファイルのフォルダを設定してしまえばよい。中間ファイルのフォルダは BaseIntermediateOutputPath プロパティで設定することができる。

  1. Visual Studio のソリューションエクスプローラから、変更したプロジェクトを選んで右クリック
  2. アンロードを選択して、プロジェクトをアンロードする
  3. もう1度右クリックして、編集を選択する
  4. プロジェクトファイルが編集モードになるので、末尾の「ここに追加のビルド手順を書いてください」的な部分にプロパティ設定を追加する

というかんじで対応できる。何も設定していないとき、

<PropertyGroup>
    <BaseIntermediateOutputPath>obj\</BaseIntermediateOutputPath>
</PropertyGroup>

と設定されているものとみなされる。また、Debug と Release といった構成名の部分まで含めて指定したい場合は Base のついていない IntermediateOutputPath というプロパティを設定すればよい。

でも、構成が増えたりプロジェクトが増えるたびにプロジェクトファイルを編集するのってめんどうだよね。というわけで、

<PropertyGroup>
    <!-- Visual Studio 2008 -->
    <IntermediateOutputPath>obj\$(OutputPath)</IntermediateOutputPath>

    <!-- Visual Studio 2010 -->
    <IntermediateOutputPath>obj\$(OutputPath.Substring(4))</IntermediateOutputPath>
</PropertyGroup>

みたいな感じで設定してしまう。$(OutputPath) は、プロジェクト設定の出力先になる。出力先を変更しているならば中間ファイルの作成先も変更しなければいけないだろう、という意味でこうしてみた。

VS2008 では文字列処理が面倒なので、出力先を "bin\Release.Customer1" としたら、中間ファイルは "obj\bin\Release.Customer1" と、先頭に obj\ を付けたものに設定し、VS2010 では先頭の4文字を捨てて obj\ を付与するため、"obj\Release.Customer1" になってくれる。*1

これで、構成ごとに対応した中間ファイルフォルダが自動的に設定されるようになり、ビルドされたマニュフェストファイルに別の構成の内容が書かれるようなこともなくなりました。

*1:先頭4文字が bin\ であることを確認するために、Conditon 属性を付けたりすると、より固いですね