はじめに
NAntとは、Ant(Javaのビルドツール)の.NET版ツールです。さまざまなタスクやファンクションが用意されていて、開発時の作業自動化や、作業の負荷軽減が可能になる便利なツールです(2006/11/27時点の最新バージョンは0.85)。NAntに関する詳細は、別稿『NAntを活用して開発時の作業を自動化する』も併せて参照してください。NAntContribはNAntの拡張版であり、NAnt用のアドオンタスクが含まれています。
本稿ではこのNAntおよび、NAntContribのVSS関連タスクを利用して、Visual Source Safe(VSS)の操作からファイルのチェックアウト、編集、コメント付のチェックインまでを自動で行います。これによって、手動で行っていた修正作業を、短時間で正確に行うことができるようになります。
対象読者
Visual Studio.NETの開発者の方。Visual Source Safe(VSS)を利用している方。コンパイル/ビルド作業、インストーラ作成自動化に興味がある開発者の方。
必要な環境
このサンプルは、NAnt バージョン0.85、NAntContrib バージョン0.85、Visual Source Safe(以下、VSS)2005、.NET Framework 2.0で動作確認を行っています。
NAnt、および、NAntContribは、以下のサイトよりダウンロードしてください。
サンプルファイル(NAntSample_VCSharp2.zip)の使用方法
サンプルファイルには、NAnt本体(バージョン0.85)、NAntContrib本体(バージョン0.85)、VSS DB、NAnt起動用バッチファイル、NAntサンプルスクリプトが含まれています。このサンプルを実行するにはVSSが必要です。
- ダウンロードファイルを「C:\」に解凍してください
- NAntを実行するため、「NAntExecute.bat」をダブルクリックしてください(「NAntExecute.bat」起動時に、「NAnt.exe」のパスが環境変数に設定されます)
サンプルスクリプト処理の流れ
サンプルスクリプト 処理の流れを、下図に示します。

VSSに自動でログインし、編集したいファイルの一覧を作成、その情報をもとにファイルをチェックアウト、編集し、コメントを付けてファイルのチェックインを行います。
以下にサンプルスクリプトの内容を解説していきます。
サンプルスクリプト:ターゲットごとの解説(1/2)
このスクリプトは、以下の6つの、「設定」および「ターゲット」で構成されています。
- プロジェクト設定/プロパティ設定
- mainターゲット
- VssLocateFilesターゲット
- VssCheckoutFilesターゲット
- UpdateAssemblyInfoFilesターゲット
- VssCheckinFilesターゲット
それでは、各「設定」および「ターゲット」について、解説していきます。
プロジェクト設定/プロパティ設定
NAntスクリプト冒頭部分で、スクリプト内で利用する値をプロパティとして設定しておきます。何度も利用する値などを、まとめて設定しておくと便利です。
ここでは、以下のプロパティを設定しています。
プロパティ名 | 説明 |
old.ver | アセンブリの旧バージョン(4桁の数字) |
new.ver | アセンブリの新バージョン(4桁の数字) |
temp.path | ファイル編集作業用のワークスペース |
vss.path | VSSのコマンドライン版であるss.exeのパス |
user | VSS DBのログインユーザー名 |
pass | VSS DBのログインパスワード |
local.path | VSSのローカルワークスペース |
ssdir | VSS DBの設定ファイル(~.iniファイル)のパス |
exList | 編集対象から除外するVSS DBのプロジェクト |
また、今回のサンプルに含まれるVSS DBのディレクトリ構成は下図のようになっています。

このうち、exList
プロパティで設定した「$/Prj3」プロジェクト、「$/Prj4/Prj4-1」プロジェクトは、編集の対象としません。
mainターゲット
mainターゲットは、メインとなる処理を行うターゲットです。
mainターゲット 処理の流れ
- ファイル編集作業用のワークスペースを作成します。
- 新旧アセンブリバージョンのプロパティ値を設定します。
- VSSに対する操作、および、アセンブリ情報ファイル編集に利用するプロパティ値を設定します。
- VssLocateFilesターゲットを実行します。このターゲットは、VSS DBに存在する「AssemblyInfo.cs」ファイルを検索し、ファイル名の一覧を作成します。
- VssCheckoutFilesターゲットを実行します。このターゲットは、ファイル名の一覧に存在する、すべての「AssemblyInfo.cs」ファイルをチェックアウトします。
- UpdateAssemblyInfoFilesターゲットを実行します。このターゲットは、すべての「AssemblyInfo.cs」ファイルに内に記述されているアセンブリバージョン情報を編集します。
- VssCheckinFilesターゲットを実行します。すべての「AssemblyInfo.cs」ファイルについて、コメント付きでチェックインします。
<target name="main" depends="" > <!-- 1. --> <mkdir dir="${temp.path}" /> <!-- 2. --> <property name="new.ver.long" value="${string::substring(new.ver, 0, 1)}.${string::substring(new.ver, 1, 1)}.${string::substring(new.ver, 2, 1)}
.${string::substring(new.ver, 3, 1)}" /> <property name="old.ver.long" value="${string::substring(old.ver, 0, 1)}
.${string::substring(old.ver, 1, 1)}.${string::substring(old.ver, 2, 1)}
.${string::substring(old.ver, 3, 1)}" /> <!-- 3. --> <property name="rcs.target" value="AssemblyInfo.cs*" /> <property name="comment" value="Changed version to ${new.ver}." /> <property name="fileList" value="${temp.path}\AssemblyInfoList.txt" /> <!-- 4. --> <call target="VssLocateFiles" /> <!-- 5. --> <call target="VssCheckoutFiles" failonerror="false" /> <!-- 6. --> <call target="UpdateAssemblyInfoFiles" failonerror="false" /> <!-- 7. --> <call target="VssCheckinFiles" /> </target>
次に、mainターゲット内で実行される各ターゲットの詳細を、説明していきます。
VssLocateFilesターゲット
VssLocateFilesターゲットは、ソース管理にあるファイルをワイルドカードで検索し、該当するファイルの名前を、指定されたファイルへ出力します。
VssLocateFilesターゲット 処理の流れ
- VSSのコマンドライン版である「ss.exe」を実行し、ファイルリスト作成用一時ファイル(${fileList}.tmp)に出力します。VSS DBに存在するファイルやディレクトリの検索には、「ss.exe」のLocateコマンドを利用します。
- 「ss.exe」を実行するために、環境変数「
ssdir
」を作成して、操作対象とするVSS DBのディレクトリを設定します。 - execタスクの
environment
属性を利用して、環境変数「ssdir
」を指定、arg
属性を利用して、LocateコマンドおよびVSS DBのユーザー名を指定します。 fileList
プロパティで指定されたファイルリストが存在する場合、削除します。- 編集対象のファイルリストを作成するために、ファイルリスト作成用一時ファイルを読み込み、各行について、5.~7.の処理を繰り返します。
- 編集対象かどうかを判定するフラグとして、
isValid
プロパティを定義します。 - パスが「$」で始まっていない行は、フラグを「false」とし、編集対象から除外します。
exList
プロパティで指定されたプロジェクトに存在するファイルは編集対象外なので、フラグを「false」にします。- フラグが「true」の行のファイルに関しては、
fileList
プロパティで指定されたファイルリストに出力します。 - 全行の読み込みが終了したら、ファイルリスト作成用一時ファイルを削除します。
<target name="VssLocateFiles" depends="" > <!-- 1. --> <exec program="${vss.path}\ss.exe" output="${fileList}.tmp" > <!-- 2. --> <environment> <variable name="ssdir" value="${ssdir}"/> </environment> <!--3. --> <arg line="Locate ${rcs.target} -Y${user}" /> </exec> <!-- 4. --> <delete file="${fileList}" if="${file::exists(fileList)}" /> <!-- 5. --> <foreach item="Line" in="${fileList}.tmp" property="path"> <!-- 6. --> <property name="isValid" value="true" /> <!-- 7. --> <if test="${not string::starts-with(path, '$')}" > <property name="isValid" value="false" /> </if> <!-- 8. --> <foreach item="String" delim=";" in="${exList}" property="exPath" > <if test="${string::starts-with(path, exPath)}" > <property name="isValid" value="false" /> </if> </foreach> <!-- 9. --> <if test="${isValid=='true'}" > <echo file="${fileList}" message="${path}" append="true" /> </if> </foreach> <!-- 10. --> <delete file="${fileList}.tmp" /> </target>