特集

MSBuild完全攻略(後編)

ビルド・エンジン「MSBuild」を思いのままに操る技

デジタルアドバンテージ 一色 政彦
2006/05/13

Page1 Page2 Page3

5. MSBuildを思いのままに操る技

 最後に、MSBuildにない独自の機能を追加する方法を説明して、本稿を終わりとしたい。ここでいう独自の機能とは、「カスタム・タスク」と呼ばれるもので、前述したターゲット(=処理プロセス)から呼び出される細かな処理作業のことである。

 ここでは、Buildターゲットから呼び出される「ビルド終了後」の処理プロセス(=AfterBuildターゲット)の中に、ビルド完了通知メールを送信するカスタム・タスク(以降、SendMailタスク)を追加することにしよう。まずはカスタム・タスク自体の新規作成を行う。

カスタム・タスクの新規作成 ― クラス・ライブラリの作成

 カスタム・タスク自体は、クラス・ライブラリとして作成する必要がある。クラス・ライブラリは、通常どおり、VS 2005のIDEで作成すればよい。ここでは、「SampleTasks」という名前のクラス・ライブラリをC#で作成することにしよう(もちろんVisual Basicが得意な場合はVBで作成してもよい。本稿ではVBのコードは割愛する)。

 次の画面は実際にそれを行っているところだ。

VS 2005によるクラス・ライブラリの作成
カスタム・タスクはマネージ・コードのクラス・ライブラリとして実装する。
  メニュー・バーから[ファイル]−[新規作成]−[プロジェクト]を選択して[新しいプロジェクト]ダイアログを表示し、そこで「クラス ライブラリ」を作成する。本稿では「SampleTasks」という名前のクラス・ライブラリのプロジェクトを作成した。
  [ソリューション エクスプローラ]の「参照設定」を右クリックして表示されるコンテキスト・メニューから[参照の追加]を選択する。[参照の追加]ダイアログが表示されるので、[.NET]タブを開いて「Microsoft.Build.Framework」「Microsoft.Build.Utilities」というコンポーネントを選択して[OK]ボタンをクリックし、これらのアセンブリへの参照を追加する。この2つのアセンブリへの参照は、MSBuildのカスタム・タスクを作成するうえで必須だ。
  1つ1つのカスタム・タスクはクラスとして実装する。本稿では、デフォルトで新規作成される「Class1.cs」というファイル名を「SendMail.cs」に変更した。

カスタム・タスクの新規作成 ― クラスの作成

 1つのカスタム・タスクは1つのクラスで実装する。カスタム・タスク用のクラスを作成する方法は、次の2種類が提供されている。

(1) ヘルパー・クラスであるTaskクラスから派生する
(2) ITaskインターフェイスを直接実装する

 本稿では、このうち実装がより容易な(1)のTaskクラス(Microsoft.Build.Utilities名前空間)の派生クラスを実装する方法を紹介する。

 ここでは、SendMailタスクを実装するクラスとして、(Taskクラスを継承した)「SendMailクラス」を作成した。具体的なソース・コードは次のとおりだ(内容についてはコード中のコメントを参考にしてほしい)。

using System;
using System.Net.Mail;

// MSBuildのカスタム・タスクを作成するには
// 次の2つの名前空間を追加する。
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

namespace SampleTasks
{
  // -----------------------------------------------------
  // メールを送信する機能を持つクラス
  // -----------------------------------------------------
  // Task派生クラスがそのままMSBuildのTaskタグになる。
  // この例では「<SendMail>タグ」を作成している。
  public class SendMail : Task
  {
    private string hostServer;
    private string mailAddress;

    public SendMail()
    {
      hostServer = "mail.d-advantage.com"; // デフォルト値
    }

    // -----------------------------------------------------
    // メール・サーバ名を取得・設定するプロパティ
    // -----------------------------------------------------
    // プロパティはTaskタグの属性になる。
    // ここでは「<SendMail>タグのHost属性」を作成している。
    public string Host
    {
      get { return hostServer; }
      set { hostServer = value; }
    }

    // -----------------------------------------------------
    // メール送信先アドレスを取得・設定するプロパティ
    // -----------------------------------------------------
    // Required属性を付加したプロパティは、
    // Taskタグの<必須>属性となる。
    // ここでは「<SendMail>タグのAddress属性」を作成している。
    [Required]
    public string Address
    {
      get { return mailAddress; }
      set { mailAddress = value; }
    }

    // -----------------------------------------------------
    // メールを送信する機能を実現するメソッド
    // -----------------------------------------------------
    // オーバーライドしたExecuteメソッドには
    // タスクの実行内容を記述する。
    // 戻り値は、タスクが成功ならtrue、失敗ならfalseにする。
    // ここでは「メール送信処理」を実装している。
    public override bool Execute()
    {
      SmtpClient mailer = new SmtpClient();
      mailer.Host = hostServer;
      mailer.Send(
        "builder@d-advantage.com",  // Fromアドレス
        mailAddress,                // Toアドレス
        "ビルド完了通知メール",     // 件名
        DateTime.Now.ToString() +   // 本文
        "\r\nビルドが完了しました!");

      // ログ・メッセージを出力する
      Log.LogMessage(
        MessageImportance.Normal,
        "SendMailタスクを実行しました。");

      return true;
    }
  }
}
カスタム・タスクを新規に実装したソース・コード
コードの内容についてはソース・コード中のコメントを参考にしてほしい。

 このコードを見れば分かるように、オーバーライドしたExecuteメソッド内にカスタム・タスクの処理内容を記述する。ちなみに、TaskクラスのLogプロパティ経由でTaskLoggingHelperクラス(Microsoft.Build.Utilities名前空間)が持つLogMessageメソッドを呼び出すことで(=上記コードの「Log.LogMessageメソッド」のこと)、簡単にログを出力できる(これは結果的に、MSBuildのビルド実行中のコンソールに対してメッセージを出力することとなる)。

 MSBuildファイルの設定内容から何らかの値をパラメータとして受け取りたい場合は、クラスのプロパティを実装すればよい。このクラス・プロパティが実装したカスタム・タスクのタグが持つ属性になる。さらにこのプロパティにRequired属性(Microsoft.Build.Framework名前空間)を付加すれば、その属性の指定を必須化できる(これにより、MSBuildファイルでこの属性を指定しなければエラーになる)。

 クラス名がそのままカスタム・タスクのタグ名となるため、本稿の例では「<SendMail>」というタグを実装したことになる。そして、そのタグがHost属性(任意)とAddress属性(必須)を持つことになる。

カスタム・タスクの利用方法 ― MSBuildファイルの編集

 以上のプログラムをビルドして「SampleTasks.dll」というアセンブリ・ファイルを生成し、それを「C:\MSBuildSample\SampleTasks\」に配置したとしよう。次のコードは、このアセンブリ・ファイルを使用してSendMailタスクを実行するMSBuildファイルの例である。

<Project
  DefaultTargets="Build"
  xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  <ItemGroup>
    <Compile Include="Program.cs" />
  </ItemGroup>

  <!-- アセンブリ・ファイル名をプロパティ化 -->
  <PropertyGroup>
    <SampleTasksDir>C:\MSBuildSample\SampleTasks\</SampleTasksDir>
    <SampleTasksFile>SampleTasks.dll</SampleTasksFile>
  </PropertyGroup>

  <!-- 使用するカスタム・タスクのアセンブリを宣言 -->
  <UsingTask
    AssemblyFile="$(SampleTasksDir)$(SampleTasksFile)"
    TaskName="SendMail"/>

  <Import
    Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />


  <!-- Buildターゲットからビルド後に呼び出されるターゲット -->
  <Target Name="AfterBuild">
    <SendMail Address="developers@d-advantage.com"/>
  </Target>

</Project>
カスタム・タスクを使用するMSBuildファイルの内容
「C:\MSBuildSample\SampleTasks\」に配置した「SampleTasks.dll」というアセンブリ・ファイルを使用してSendMailタスクを実行するMSBuildファイルの例。

 このコードを見れば分かるだろうが、<UsingTask>タグのAssemblyFile属性にカスタム・タスクを実装したアセンブリ・ファイルを指定し、そのTaskName属性にMSBuildファイル内で使用したいタスクの名前を指定すればよい(ちなみに本稿の例では、タスクの名前をクラス名で指定しているが、名前空間付きのクラス名で指定してもよい。つまり“SendMail”ではなく“SampleTasks.SendMail”と指定できる)。

 後はこのカスタム・タスクをターゲットの中で呼び出せばよい。要するに、<Target>タグのスコープの中に<SendMail>タグを記述すればよいわけだ(ちなみにタスクはターゲット内に複数記述可能だ)。

 「Microsoft.CSharp.targets」で定義されているBuildターゲットの内部では、実際のビルド処理プロセス(=CoreBuildターゲット)、その前後に前処理プロセス(=BeforeBuildターゲット)と後処理プロセス(=AfterBuildターゲット)を呼び出すように定義されている。本稿では、このAfterBuildターゲットを実装し、そのターゲットの中でSendMailタスクを呼び出すようにしている。

 なおここで特に注意してほしいのは、AfterBuildターゲットの定義が「Microsoft.CSharp.targets」にもあるため(その定義内容は空なので実際には何も処理しない)、必ずMicrosoft.CSharp.targetsファイルをインポート(Import)した後にAfterBuildターゲットを記述しなければならない。こうしないと、AfterBuildターゲットを上書き(=オーバーライド)できないからである(インポートする位置を間違えると、逆に空の定義で上書きされてしまう)。

カスタム・タスクの実行結果 ― MSBuildによるビルド実行

 以上のMSBuildファイルを実行したのが次の画面である。

カスタム・タスクの実行結果
上の画面では、赤枠で囲まれた部分がカスタム・タスクの実行結果である。下の画面は受信したメールだ。

 この画面を見ると、実際にAfterBuildターゲットが実行され、「SendMailタスクを実行しました。」というメッセージがコンソール出力(=ログ出力)されているのが確認できる。

さまざまなタスクを活用しよう!

 以上で独自に作成したカスタム・タスクの利用方法はご理解いただけただろう。しかし、独自のタスクを作成しなくても、MSBuildが標準で提供するタスクや、サードパーティが提供するタスクなども活用できる。

 MSBuildが提供する主な標準タスクを以下の表にまとめた。

タスク名 説明
Copy ファイルをコピーする
Delete ファイルを削除する
MakeDir ディレクトリを作成する
RemoveDir ディレクトリ(および、そのサブディレクトリ)を削除する
GenerateResource .txtファイルや.resxファイルを.resourceファイルに変換する
Csc C#コンパイラを呼び出す
Vbc Visual Basicコンパイラを呼び出す
VCBuild Visual C++コンパイラを呼び出す
Exec プログラムやコマンドを実行する。これを活用すればコマンドラインから実行できるツールはすべて呼び出せるだろう
Message ビルド中のメッセージをログに記録する(=コマンド・プロンプトで実行するとコンソール出力される)
MSBuildが提供する主な標準タスク

 これ以外の標準タスクについては以下のWebサイトをご参照いただきたい。

 またサードパーティが提供する主なカスタム・タスクを以下の表にまとめた。

タスク 説明
FxCop マネージ・コードを解析して、デザイン・ガイドライン(コーディング規約など)に適合しているかどうかを調べるためのツールである「FxCop」を呼び出す
NDoc APIドキュメント生成ツールの「NDoc」を呼び出す
NUnit 単体テスト・ツールの「NUnit」を呼び出す
Zip ファイル群をZIP圧縮する
VssGet ソース管理ツールの「Visual SourceSafe」からプロジェクトの最新リビジョンを取り出す
サードパーティが提供する主なカスタム・タスク

 これ以外のサードパーティ製カスタム・タスク(すべてオープンソース)については、以下のWebサイトをご参照いただきたい。

 以上、MSBuildの使い方からMSBuildファイルの作成方法までをひととおり解説した。本稿の内容が読者諸氏のビルドの自動化と、それによる作業コストの軽減に役立てば幸いである。End of Article

 

 INDEX
  MSBuild完全攻略
  .NETビルド・エンジン「MSBuild」使いこなし術(前編)
    1.「MSBuild」および「MSBuildファイル」とは?
    2.コマンドラインからMSBuildを使いこなす!
 
  ビルド・エンジン「MSBuild」を思いのままに操る技(後編)
    3.MSBuildファイルの基本要素を理解する
    4. プロジェクト項目、プロパティ、条件分岐の記述
  5. カスタム・タスクでMSBuildを思いのままに操る!


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間