d.sunnyone.org
sunnyone.org

ページ

ラベル MSBuild の投稿を表示しています。 すべての投稿を表示
ラベル MSBuild の投稿を表示しています。 すべての投稿を表示

2015-10-14

MSBuildでRAW画像ファイルを移動する

正直PowerShellでOK。普通こんな使い方してないけど、なんというかItemGroupの使い方の例ということで。

デジカメで写真を撮るときは、RAW画像も一緒に撮るのだけど、オンラインなところに一緒に置いておくと容量を食うので、オフラインなところに退避したい。しかし、こんな構造で保存しているので、そのままだと散らかっていて移動させにくい。

  camera\20151014-自宅\DSC00274.JPG →これはとっておきたい
  camera\20151014-自宅\DSC00274.RAW →これは避けたい

なので、ARWだけこんな感じの場所にムーブしたい(そしたらまるっと移動させればいいので)

  camera\ARW\20151014-自宅\DSC00274.RAW

もちろんスクリプトを書けば全く問題ないのだけど、MSBuildで書いたらこんな感じになったのでメモ。camera\に配置して動かす。


2015-10-10

Visual Studioソリューションの配置方針とMSBuildの活用

Visual Studioで開発をしていると、ひとつソリューションを作ってひとつのVisual Studioインスタンスでビルドしたり発行している間は良いが、そのうちそれ以上のことをしたくなってくる。例えば、複数のソリューションを複数のVisual Studioインスタンスで開いたり、CIにリリース用のzipファイルを作らせたりといったことである。

そのような状況を踏まえながら、自分がソリューション/プロジェクトを作るときに考える点について、文書としてまとめたことはなかったと思い、以下に記述する。

Visual Studio全般に通じる部分も多いと思うが、基本的にC# プロジェクト(.csproj)を想定する。

前提: ソリューション/プロジェクトとは何か?

Visual Studioでは、アプリケーションをビルド(及び実行)するために必要なものをまとめたかたまりを「プロジェクト」と呼んでおり(*1)、「プロジェクトファイル」(*.なんとかproj)には、ファイル一覧や参照ライブラリ情報が記載されている。

*1: プロジェクトは、アプリケーションをビルドするのに必要なものすべての論理的なコンテナーです。 - ソリューションとプロジェクトの作成

その「プロジェクト」を複数まとめたものが「ソリューション」となっており、プロジェクトの紐付けの情報が記録されているのが「ソリューションファイル」(*.sln)である。Visual Studioの1インスタンスは通常ひとつの「ソリューション」を開いている。

「プロジェクトファイル」(*.なんとかproj)/「ソリューションファイル」(*.sln)は、Visual StudioのGUIによって作成/編集される。

また、この「プロジェクトファイル」(*.なんとかproj) ファイルはMSBuildというビルドツールでビルドできる形式となっている。

MSBuildから実行できるプロジェクトファイルはVisual Studioに頼らずに一から作成することもでき、MSDNのドキュメント的にはそのファイルもプロジェクトファイルと呼ぶように見えるが、本記事では便宜上そのような1から書いたファイルは区別して「MSBuildファイル」と呼ぶことにする。

単一ソリューションの場合

まずはシンプルなひとつのソリューションに複数のプロジェクトという構成。Visual Studioからソリューションを作成することのほかに、やっていることがあるので、まずはその方針について記載する。

ざっくり図で表すと、以下の通りである。


詳しく説明していくと、以下の通り。

コード記述時以外のビルドの窓口となるMSBuildファイルを用意する

コードを書いているときはVisual Studioでコードを書き、ビルドし、デバッグ実行する。それ以外の作業、例えばzipへのアーカイブであったり、サーバへのデプロイといった作業についてはVisual Studioで完結させるのではなく、Visual StudioでのプロジェクトをラップしたMSBuildファイルをMSBuild.exeなどでビルドし作業する。手続きを*.〜projに記述することもできるが、それは基本的にしない。

これをする理由の一つ目は、機械的に生成される部分と人が意図を持って記述している部分を分けることにより、人が記述している部分の書きやすさ/読みやすさを向上させるためである。ツール(Visual Studioやその拡張)が生成/編集する*.〜projファイルに記述するとなると、生成/編集するツールの都合に合わせて記述しなければならない。ただの一覧のような設定ファイルであればそれほど問題ではないが、もっと自由に記述できるMSBuildでは非常にストレスフルな作業になる。また、Visual StudioのGUIから生成したわけではない追加の記述があることがGUIから分かり辛く、気づきにくい。別に記述してあれば、これらの問題はない。

二つ目は、CIシステムからのエントリポイントとして便利なためである。.csprojは先の通りMSBuild.exeでビルド可能なのだが、複数のcsprojを順にビルドするとか、渡すパラメータがいくつもあったりすると、そのMSBuild.exeの呼び出し自体がスクリプトのようになってきて、CIシステムのジョブの見通しが悪くなったり、変更管理がしにくくなったりする。しかし、CIシステム側からはこのMSBuildファイルを呼ぶだけと決めておけば、CIシステムでのジョブの記述内容が容易に想像できるようになり、またCIシステムに設定する前のタスクの事前確認がしやすくなったりする。

なお、このプロジェクトをラップしたMSBuildファイルは、私は「{{Name}}.msbuild」というファイル名をつけることが多いが、「{{Name}}.proj」でも別にかまわないし、そっちのほうがプロジェクトファイルとしての本筋っぽくはある。.msbuildで慣れてしまったのもあるが、Visual Studioで開くファイルではないよーということがわかっていいかなと思う。(この.msbuild拡張子を使っているプロジェクトもgithubで見かけるので、それほど好き勝手ではないと思っている。例えば、xunit

MSBuildファイルは基本的にプロジェクトファイル(*.~proj)をビルドする

MSBuildは、MSBuildタスクで他のプロジェクトファイルをビルドすることができる。MSBuildファイルは、これを利用してVisual Studioで作ったプロジェクトをビルドする。

なお、ソリューションをビルドすることもできるが、余分なビルドを減らすためにも、できる限りプロジェクトファイルを指定するほうが良い。

出力用フォルダを用意して後処理を可能にする

成果物出力フォルダはbin\Debug\のような各プロジェクトのデフォルトのパスではなく、「output\」のようなMSBuildファイル処理用の出力用フォルダを設定してそこに出力するようにする。

MSBuildファイル上の記述としては、以下のようになる。これは、KiritoriMage.csprojを「Release」でoutput\KiritoriMageに出力する指示である。(OutputDirプロパティは事前に「output」と定義、MSBuildProjectDirectoryはMSBuildファイルが配置されているディレクトリ(自動定義))


これをすることで、出力用フォルダ以下は書き換え(削除)して良いことが明確になるため、様々な後処理が行いやすくなる。もちろん、bin\Debugの状態でもできなくはないのだが、「どこ?」となりにくいので処理しやすい。

後処理とは例えば、以下のようなことである。
  • MSBuildで指定した変数に応じた環境情報を設定ファイルに設定する(*2)。
  • NuGetで入れたパッケージが不要なファイルを成果物にしてくるので、削除する。
  • 動的に生成するコンテンツを成果物に含める。
*2: おすすめはしない。なぜかというと、ビルド成果物が環境に縛られるので、各環境ごとに成果物が必要になってしまうため。可能な限りデプロイ時に構成するか、環境側に設定したい。

引き続きKiritoriMageのBuildターゲットで説明するとこんな感じである。ffmpegは使わないので消している。
やりなおしたいときもこのフォルダを削除すればよいだけというのは、いろいろな意味で楽である(この削除をする「Clean」ターゲットは用意しておく)。 ただし、この出力先フォルダの差し替えをするのが面倒なプロジェクトタイプがあった覚えがあるので、労力との見合いで実施する。

csprojには、可能な限りビルド構成は増やさない(Debug, Releaseだけで行けるならそうする)

ビルドのプロパティに関しては、MSBuildファイル側からできるだけ「Release」構成にプロパティで渡して変更することとして、可能な限りcsproj側のビルド構成(Configuration)は増やさない。

理由は、ビルド構成はGUIでの設定となる都合上、どうしても設定内容をフラットに見せざるを得なくなるため、各構成間での差分に対する見通しが悪かったり(良く見せることが難しい、と言うべきか)、一部のみ違う構成の変更作業に手間がかかったりするためである。MSBuildファイル中にコードで指示していれば「このプロパティだけ違う」というのが意図として伝わりやすい(伝えるコードに書きやすい)。

プロパティで変更できなくても、XMLな設定ファイルがちょっと違うレベルなら、ビルド後にMSBuild Community TasksのXmlUpdateで更新してしまうという手もある。

この方針も、構成間の差分次第で考える。がっつり違うのであれば、別物として用意しておくのもひとつ。

ツール群は窓口MSBuildファイルから呼べるようにする

そのプロジェクトの便利ツールがある、といった場合、窓口となるMSBuildファイルにタスクを記述しておくと、そこに存在があること、及びどんなパラメータが必要なのか明確になって便利である。CIからも呼びやすい。

正直これが便利だといえるのは、MSBuild LauncherのUIがこうだからというのも大きいが、この話だけ切り取って説明したのが「PowerShellにMSBuildLauncherで簡易GUIをつける」で、詳しい話はこちらを参照されたい。

複数のソリューションを使う場合とは

さて、複数のソリューションの方針を説明する前に、どんなときに複数になるのかという話。

Visual Studioは、基本的に一つのソリューションに対して同時に一つのデバッグ実行を行うことが想定されている(ように私には見える)。そのため、複数の実行が同時に走るようなものを一つのソリューションに押し込むと、扱いにくい(一応実行はできなくはない)。例えば、Webサーバーをデバッグ実行しながらクライアントアプリをデバッグ実行するといったケースでは、サーバー側、クライアント側でそれぞれソリューションを作成すると、二つのVisual Studioを同時に起動し、それぞれでデバッグ実行を行えて便利である。

そのため、同時に利用する複数のエントリポイントがある場合、複数のソリューションを使う。

他にも、ビルドの粒度のコントロールのために分割するという話もあるかもしれない。

複数ソリューションの場合

上記の状況となる典型的なケース、ServerとClientが及びその共通部分であるCommonというソリューションを構成する場合を例に複数ソリューションの場合の方針について記載する。 まずは図で表すと、以下の通りとなる。


なお、後の説明が通じやすいようにCommon, Server, Clientという名前をつけただけで、名前のつけかたはここでは触れない。Sharedといった他の汎用的な名前であったり、あるいはコードネームだったりとか、そういったものでも別に構わない。

各ソリューションごと、及びソリューションのまとまりごとにMSBuildファイルを用意する

先ほどのMSBuildファイルは、各ソリューションごと(子)、及びそのまとまりごと(親、通常トップにひとつ)に定義する。

子のMSBuildファイルには、各ソリューションごとの作業を記述する。親のMSBuildファイルには、MSBuildタスクによる子のターゲットの呼び出しと、組み合わせたときに必要になることを記述する。(とくになければ親側は単なる窓口になる。)

別のソリューションのプロジェクトを参照してもよい

例えば、CommonのプロジェクトはServerとClientが参照してもOK。すべては追加せず、必要な分だけ参照する。

ただし、基本的にはCommonへのメソッドの追加などはCommonのソリューションを開いて実施する。read-onlyとは言わないが、あくまで使っている側は参照用というスタイルで使う。 というのも、Common側でビルドが完結することがはっきりしないといけないし、ユニットテストが実施できないからである(ServerやClientからCommonのユニットテスト プロジェクトへの参照があるのはおかしい)。

とはいえ名前変更のようなリファクタのときは入っているほうがよかったりするので、どちらで直していいかはケースバイケースではあるが。

(大規模な変更をするときは、merge-solutionsで全部入りのAll.slnというのを作ったりするがこれは完全にバッドノウハウ。)

共通の定義を記述するMSBuildファイルを用意する

複数のプロジェクトにまたがって利用できる共通のターゲットがあれば、~.targetsという形で共有する形で追い出す。

ディレクトリ階層は揃える

これはバッドノウハウではあるのだが、csproj内には相対パスで参照される項目があるので、csprojがあるフォルダ階層は可能な限り揃えるようにする。 例えば、こんな感じ。

  • XYZ.Server.Web\XYZ.Server.Web.csproj
  • XYZ.Client.App\XYZ.Client.App.csproj

内部であってもNuGetパッケージを作成して利用する

上述のCommonは、共通に利用するアセンブリがあるということしか意味しないので、便利コードのようなものは、内部であってもNuGetパッケージにしてプライベートリポジトリで配布するとよい。

標準のファイルシステムベースのプライベートリポジトリという方法(社内の開発環境の改善&効率化のためにNuGetを活用しよう - Build Insider)もあるが、ProGetのようにこのようなパッケージを管理できる製品もある。また、使ったことはないがMyGetのようなSaaSも利用できるだろう。

なお、チームが分割されている場合、例えば「共通基盤チーム」が存在する場合、NuGet配布にするとリリースサイクルなどがコントロールしやすくなる場合もある。配布元チームは利用側チームに適切なリリースとして見せられるし、利用側チームは適切なタイミングでバージョンアップできるからである。

その他のTips

MSBuild Community Tasksの活用

MSBuild Community Tasksというものがあり、Zipを作ったり、Version情報を生成したりするTaskなどがあるので、NuGetでインストールして活用する。

csprojから参照されるtargetsファイルの構造に深入りしない

前述の通り、csprojファイルはMSBuildのプロジェクトファイルである。そのため、ビルド方法を記述したファイルをImportしており、追おうと思えばビルド作業を追うことができる。

しかし、決して処理順や参照変数などを追いやすい構造ではなく、これをやり始めるとそればっかりになってしまって、割に合わない。そして頑張って調べても、Visual Studioなどのバージョンによって変わってしまう可能性がある。

そもそも動かないといったトラブルシューティング的な部分であれば仕方ないが、~~というオプションがあれば後処理がいらなくて済むのになぁといった話は、時間を区切ってわかるレベルに留めるのが無難と思う。

MSBuildは、便利に使える範囲で使って、そこから出たらPowerShellなどのプログラムに任せる。

MSBuild Launcherの活用

上述のMSBuildファイルはVisual Studioで開くためのファイルではないので、Visual StudioをGUIとしては使えないか、あるいは無理に使えるように作ってもVisual Studioがいろいろなターゲットを実行するために作られたUIではないので不便である。

普通に考えるとMSBuild.exeで実行することになるが、そうなると「そうは言っても毎回コマンドを実行するのは辛い」という流れになり、GUIが欲しくなる。でもいいのがないね、という話で作ったのがMSBuild Launcherなので、そういう感じになったら使ってみてほしい。

例としてKiritoriMageのMSBuildファイルを開いた様子はこんな感じである。


なお、今よりもずっとノウハウがないときのプロジェクトなので全体のサンプルとしておすすめできるプロジェクトではないが、一例としてKiritoriMageのMSBuildファイルとしてはだいたいこんな感じである。

おわりに

自分でも、最初からこういうふうに作るわけではなく、ソリューションとプロジェクトファイルしかない場合や、ソリューション側のmsbuildがなかったりと、実際のところはもう少しいろいろ違っている。

いろいろ作ってきていないもの(Portableライブラリ, ストアアプリなど)もあるので、配慮が欠けている部分もあるかもしれない。とはいえ、少しでも設計の参考になれば幸いである。

なお、最新にはついていっていない部分があるはずなので、変わっている部分があればぜひ教えて欲しい(DNXの影響はかなりありそう)。

2014-04-24

MSBuild Launcher 0.2.3 リリース

MSBuild Launcher 0.2.3をリリースしました。

今回の大きな変更点の一つ目はパフォーマンス改善です。生産性が上がるというレベルの変化なのでぜひ上げてください。処理待ちよりもログ出力待ちのほうが多いなんてビルドをされている方には、体感でわかるレベルで違うはずです。PowerShellで適当に出力して確認していたら、2倍ぐらい速くなっていました。


確認に使っていたビルドファイル:


もうひとつはキャンセルをするときに再帰的にプロセスを停止するようにしたことです。今まではエンジン用プロセスだけ停止していたので、Execで起動するようなケースではプロセスが残ってしまったりしたのですが、子供から殺すのでいなくなるはずです。

2013-12-22

PowerShellにMSBuildLauncherで簡易GUIをつける

今日のPowerShell勉強会第1回の運営の方々、発表者の方々、そして参加者の方々お疲れ様でした。どれも面白かったり勉強になったりでよかったです。

さて、Lightning Talkで掲題の話をしたのですが、実用するには速すぎてわからなかったと思うので読み物としてわかるようにまとめたいと思います。

概要

MSBuild(.csprojなんかで使われている)はビルドには必要なんだけど、ちょっとコマンドライン叩くの面倒だよね、適当なGUIないよね。
  →MSBuild Launcherの誕生。

あれ、このGUIなら逆にビルドじゃない用途でも(スクリプト実行の用途でも)MSBuildにExec書いて使ったら便利なんじゃね?
  →MSBuild LauncherありきのMSBuildの邪道な使い方の誕生。

というお話です。

前提として、MSBuild Launcherをインストーラでインストール(関連付けオプション有効)を想定しています。

---

1. シンプルな使い方

単純に.ps1ファイルを置いて、それを実行するだけ。これでも十分に便利。一応、コマンドが長くなりすぎちゃうので、プロパティ(※1)としてpowershellコマンドを別出しにしておくのがおすすめ。

※1: パラメータのようなもの。PropertyGroup要素に好きな名前の要素を置くと、それがプロパティになる。



なお、-NonInteractiveは常に入れておくのがおすすめ。発表時も話したけども、例えば必須引数が足りなかったりすると通常のコンソールでは入力待ちで止まるけども、こいつはそんなことできないので、無言で待ちに入る。そして「進まない!」と悩む。なので-NonInteractiveで即座にエラーにする。

対応するスクリプトは好きな処理を書けばいいのだけど、一応例として。



動かすとこんな感じ。


2. プロパティを持たせる使い方

パラメータが欲しいときは、MSBuildにプロパティを持たせるとよい。そしてコマンドの中で$(Name)で使う。
ただし、Exec Command=""の中身の文字列はcmd解釈?のようなので注意。Command=をくくるのは""にして、プロパティを'$(Name)'という感じにくくるのがおすすめ。



プロパティはLTでは話さなかったけども、候補としてConditionを追加してあげると、コンボボックスの選択になるので、選択のときはそうしてあげるとよいかも。

スクリプトはこんな感じ。paramで受けてあげればいい。



動かすとこんな感じ。右側で設定できる。


3. 複数のターゲットを用意する便利な使い方

複数のやりたいことを一つの画面で行うには、もちろんスクリプトを複数用意してもよいのだけど、処理自体は少ない場合は、モジュール(.psm1)に関数を定義して、それをMSBuildから使う方式がおすすめ。

具体的には、PSCmdの中にImport-Moduleまで入れてしまって、Execの中では関数名を書く形にする。



スクリプトはこんな感じ。



動かすとこんな感じ。


4. PowerShellの便利機能を活用する

PowerShellを簡易GUIっぽくしちゃうことで有名なOut-GridViewやShow-Commandはここでも便利。
ただ1点注意があって、Execで実行するとコンソールと違ってホストが残らないので、そのままだとすぐ画面がいなくなってしまう。
なので、以下のように終了を待ってあげるのがいい。


---
今度こそぜひ活用してあげてください。

2013-11-30

MSBuild Launcher 0.2.2 をリリース

MSBuild Launcherの0.2.2をリリースしました。「ターゲットがたくさんあるMSBuildファイルで、何度も同じものを実行したいときに今のUIだとつらい」という要望があったので、前回実行したターゲットの色を変えるようにした、というのが今回の変更です。


あと、WindowsXPでクラッシュする問題への対策もだいぶ前に入れたので、今は大丈夫のはずです。

2013-03-08

MSBuild Launcher 0.2.0 リリース

MSBuild Launcher 0.2.0が出ました

0.1.xのヘンテコなJSON記法は廃止し、プロパティはファイルから取るようになりました。
右のFile Propertiesには、ImportedだとかSpecialなプロパティは出てこない(あると出すぎる)ので、
もし必要であれば、Settingからプロパティ名を追加してください。特殊なプロパティも定義されていれば表示されます。

あと、インストーラができたので、そのほうが好きな方はどうぞ。関連付けができます。
ただ、一度手動で関連付けていると、関連付かないことがあるので、そのときはいったんアンインストールして
HKCRのゴミを消してからまたインストールしてみてください(ちょっとひどい話ですが)。

---
WiXでのインストーラの作り方も記事にしようかと思ったんだけど、あまり「これだ!」という感じにならなかったので、見送り。

2013-02-19

MSBuildからAssemblyInfoを生成する

結論から言うと、MSBuild Community TasksAssemblyInfoタスクを使えばできる。

おすすめじゃない方法

おすすめじゃないけど簡単な方法として、既存のAssemblyInfo.csを置き変えてしまう方法がある。
Community Tasksの.targetsをImportしたあと、以下の感じのターゲットを作れば、既存のAssemblyInfo.csを置き変えることができる。



しかし、この方法ではプロジェクトが複数あった場合に、プロジェクト別に値を設定することができない。
これを作ったあと、Community Tasks的におすすめな方法があることがわかった(雛形がある)。

おすすめの方法

ざっくり言うと、GlobalAssemblyInfo.csを作り、それを参照する。

1. GlobalAssemblyInfo生成ターゲットを作る

Community Tasksをインポート後、このようなターゲットを作る。


次のプロセスのために1回実行しておく。

2. GlobalAssemblyInfo.csをリンクとして追加する

各プロジェクトで、GlobalAssemblyInfo.csを追加する。Visual Studioからは、「追加>既存の項目...」で追加するが、
追加ボタンの右の▼を押して、リンクとして追加するのを忘れない。


3. 既存のAssemblyInfo.csから重複する値を削除する

GlobalAssemblyInfoに定義した値は、既存のAssemblyInfo.csから削除しておく。

これで、各プロジェクト個別の値をセットすることを可能にしつつも、バージョン等々をMSBuildから管理できるようになった。

GlobalAssemblyInfoの情報を取得する

アセンブリの情報は、リフレクションで取得することが可能だが、GetCustomAttributesが冗長な記述を要求したりして面倒。
しかし、AssemblyInfoタスクで、GenerateClass="true"にしておくと、「ThisAssembly」クラスを作ってくれる。
そのため、以下のようなシンプルな形でコードから情報を取得可能。

  string product = ThisAssembly.AssemblyProduct;

2013-02-06

MSBuild Launcher 0.1.0 リリース

最近またMSBuildをちょっと使うようになったので、MSBuild Launcherの新版をリリースしました。
  http://msbuildlauncher.codeplex.com/
githubダウンロード機能削除を受けて、これもCodeplexに移行です。

あと、プロパティ編集機能という大き目の機能がついたので、0.0.3ではなく0.1.0になりました。

MSBuildファイルの中のコメントに以下の感じのJSONを書くと、右側のペインにテキストボックスかコンボボックスが現れます。


本当はオレオレnamespaceを用意してオレオレ属性をプロパティのタグにつけたかったんだけど、そういうXMLファイルは食べてくれなかったので仕方なく。コメントの中にXMLが現れるとまたカオスなことになりそうなので、いっそJSONということでJSONになりました。

ちなみに上の「Common Properties」は実行ファイルと同じ場所にあるCommonProperties.jsonというファイルにJSONが書かれています(編集可能)。

これらのプロパティは、変更したものだけ(=右側のトグルボタンがオンになっているときだけ)ビルド時に指定されるようになっています。


あとは、似非Editボタン(.xmlに関連付いたプログラムを起動する)とか、既定のターゲットを実行するBuildボタンがついたりしました。

[2013/2/7追記]
いくつかバグってたので直して0.1.1を出しました。疑似Editボタンは、設定を用意してちゃんと(?)Editボタンになりました。

[2012/2/9追記]
MSBuild LauncherのビルドをMSBuildでやるようにした関係もあって、0.1.1はAnyCPUにしたんだけど、x64環境ではx86のアセンブリがロードできずに動かないケースがあるとのこと。 そりゃそうだ。ということで、0.1.2が出て、x86に戻りました。うざったいメッセージボックスもログウィンドウに出してうざくなくしたよ。


2012-11-10

MSBuild Launcher 0.0.2リリース

MSBuild Launcher 0.0.2をリリースした。
 https://github.com/sunnyone/MsbuildLauncher/downloads

キャンセル機能がついた。といっても、ビルド処理を別プロセスで立ち上げてキャンセルしたいときはKillするというアグレッシブな仕様だけど。

2012-10-27

MSBuild Launcher 0.0.1をリリース

ここでちょっと触れたMSBuildの良いGUIが見つからなかったので、さくっと作った。

ダウンロードはこちらから。
https://github.com/sunnyone/MsbuildLauncher


MSBuildファイルを開くと、左側にターゲットのボタンができるので、クリックすれば実行される。
コマンドライン引数にも対応しているので、.msbuildを関連付けることも可能。

2012-06-12

PowerShellをMSBuildから呼び出す

MSBuildは、MSの世界のAntのようなもの。そのMSBuildから、PowerShellのスクリプトブロックを呼び出す方法。

きれいな方法を目指すのであれば、PowerShell MSBuild Taskというものがあり、そのTaskを呼び出してPowerShellを実行すればよいのであるが、入っているdllが32bitであった。

32bit版MSBuildから呼べばいい話なのだと思うが、他のツールとの関連が面倒なので、本エントリでは安直にpowershellコマンドを呼ぶ方法を紹介する。

単純に書けば簡単で、Execタスクを利用して、powershell -Command "& { }" を呼び出せばよい(この表記については、PowerShell.exe コンソールのヘルプを参照。)

ただし、生で記述するとごちゃごちゃするので、MSBuildのPropertyGroupの中に、コマンドの始まりと終わりの文字列をPSBegin, PSEndなどとして定義し、ExecのCommand属性で$(PSBegin) $(PSEnd)などのように使うことで、ちょっときれいに書ける。
 
 例は以下のとおり。


上述のように、Invoke-Commandを使ってのリモートの呼び出しを塊にしておけば、リモート呼び出しもさっくり書ける。(リモートからPowerShellを呼ぶ環境を作るのが難しいのはまた別の話。)

参考:http://blog.brianhartsock.com/2009/10/20/using-powershell-scripts-from-msbuild-scheduled-tasks-etc/


まったく余談だが、勝手な要素をどんどん作っていくのがキモチワルイ...