kazuk は null に触れてしまった

C# / .NET 系技術ネタ縛りでお送りしております

カテゴリーアーカイブ: VS2010

Multi Project な Project Template を作成する


元ネタは

How to: Create Multi-Project Templates
http://msdn.microsoft.com/en-us/library/ms185308.aspx

なんだけど、一回作ってる最中にうまくビルドできなくなったので、メモとりながら「やってみる」という blog

要 Visual Studio SDK です。

プロジェクトテンプレートのプロジェクトを作成。ソリューションエクスプローラー上での構造があうように作る。

imageimage

<?xml version="1.0" encoding="utf-8"?>
<VSTemplate Version="3.0.0" 
            Type="ProjectGroup"
            xmlns="http://schemas.microsoft.com/developer/vstemplate/2005">
  <TemplateData>
    <Name>LibWithUnitTest</Name>
    <Description>&lt;No description available&gt;</Description>
    <Icon>LibWithUnitTest.ico</Icon>
    <ProjectType>CSharp</ProjectType>
    <RequiredFrameworkVersion>2.0</RequiredFrameworkVersion>
    <SortOrder>1000</SortOrder>
    <TemplateID>526730eb-c930-4614-8398-64a21c9f008a</TemplateID>
    <CreateNewFolder>true</CreateNewFolder>
    <DefaultName>LibWithUnitTest</DefaultName>
    <ProvideDefaultName>true</ProvideDefaultName>
  </TemplateData>
  <TemplateContent>
    <ProjectCollection>
      <ProjectTemplateLink ProjectName="Implementation">
        ClassLibrary\ClassLibrary.vstemplate
      </ProjectTemplateLink>
      <ProjectTemplateLink ProjectName="UnitTest">
        UnitTest\UnitTest.vstemplate
      </ProjectTemplateLink>
    </ProjectCollection>
  </TemplateContent>
</VSTemplate>

あれ、ビルドできた。(ぉぃ

んでプロジェクトの追加したら普通にできた。(ぉぃ

 

企画倒れ!

…となぜ最初のは失敗したのかなと。 .cs のファイルプロパティで、ビルドアクションは「なし」にしてないと駄目。子プロジェクト側 vstemplate のビルドアクションは「なし」にした方が良いみたい。(VSTemplate ビルドアクションになってるとその分 Project Template の zipが吐かれますね)って事で、ファイルプロパティの設定間違ってるだけでした。

imageimage

っていう感じですね。

ってここまで書いてからこんなの見つけちゃった。

Multi-Project Templates with Wizard: Visual Studio 2010 Sample

http://vsix.codeplex.com/

プロジェクト作成時の Wizard まで実装してるね!コッチでも子プロジェクトの vstemplateのビルドアクションは無しになってますね。

http://vsix.codeplex.com/SourceControl/changeset/view/61761#1354286

<ItemGroup> <None Include="Children\Windows Library\ProjectTemplate.vstemplate" /> </ItemGroup>

ほら、無し(None)でしょ。

広告

Implementing Visual Studio Custom Tool step by step


環境の準備

というわけで Visual Studio でのカスタムツールの実装方法です。

まず最初に Visual Studio 拡張のSDKが必要になりますので、ダウンロードしてインストールしてください。 Extending Visual Studio から Visual Studio 2010 SDK

で、非常に定型コードの多い、カスタマイズの必要のない部分が多いので、Razor Preprocessor のソースを持ってると非常に楽です(っていうか、とってきてそのままプロジェクトに入れて下さい的解説が多く出ます)ので zip は拾って展開しておいてください。

プロジェクトの作成

Visual Studio 2010 SDK をインストールすると、Extensibility 配下に VS Package プロジェクトが表示され、Visual Studio 拡張のパッケージを作成する事ができます、この VS Package プロジェクトにカスタムツールを実装する事になります。

プロジェクトを作成したらまず vsix のマニフェスト編集になります。ここで一番重要なのは統合対象のVSエディションの選択です、デフォルトでは Professional のみになってますので必要な統合先を選択してください。

image image

プロジェクトビルドオプションの設定

Visual Studio 2010 では基本的に MEF による拡張になっている為、VS Package はデフォルトで COM 公開になっていません。これを有効にします。プロジェクトのプロパティでアセンブリ情報をクリックし、アセンブリをCOM参照可能にします。

image image

参照設定

VS Package の標準参照設定では Custom Tool を実装する上でのインターフェース定義等いくらか不足しますので、これを参照設定を行い取り込みます。

image

追加されている主な物はEnvDTE80, Microsoft.VisualStudio.OLE.Interop, Microsoft.VisualStudio.Shell.Inteop, VSLangProj, VSLangProj80ぐらいですね。その他の System.Web 配下とかは今回 Razor のコード生成が必要だったのでくっついてるだけで、Custom Toolの実装に必要というわけではありません。Visual Studio の NoPIA のデフォルト動作が VS 連携がらみのシナリオとバッティングをおこしビルド時に警告が出るようになると思います。VS連携系のアセンブリの参照設定時には「相互運用機能の埋め込み」はFalseを指定してください。

image 

pkgdef 属性定義宣言

カスタムツールは COMモジュールであり、VS からレジストリを介して参照されますので、パッケージのインストール時に pkgdef によるレジストリ設定を行う必要があります。このレジストリ定義をvsixインストーラーが解釈可能な形で渡すためにアセンブリ内のクラス宣言に付与した属性から抽出する仕組みが Visual Studio SDKには含まれています。RegistrationAttribute(Microsoft.VisualStudio.Shell.RegistrationAttribute クラス) はあまりに汎用過ぎてモジュール定義的な内容しか出力できないので、この属性定義の派生を作成します。CodeGeneratorRegistrationAttributeクラスがこの実装になります。カスタムツールのpkgdefを生成する上でいじるところは特にないのでそのままソースをプロジェクトに組み込んでください。

IVsSingleFileGenerator の実装

IVsSingleFileGenerator を実装します、COMインターフェースなんでメモリ管理面等気を使わなければいけない部分が幾つかあるのですが、必要十分な実装が BaseCodeGenerator.cs にありますのでこれを取り込みます。

同じく IObjectWithSiteも実装しなければならないのですが BaseCodeGeneratorWithSite.cs に必要十分な実装があります、この実装を取り込む事で Visual Studio のプロジェクトシステム内のサービス提供モデルに組み込まれる事ができ、結果的に VSLangProj等のインターフェースが利用可能になります。(この時にエラーメッセージの文字列リソースとして Strings.resxが必要になります。 resx を取り込んでカスタムツールに ResXFileCodeGenerator を指定してください)

最終的に Custom Tool の実装はここで準備した BaseCodeGeneratorWithSite から派生されます。

カスタムツール本体の実装

BaseCodeGeneratorWithSiteの継承クラスを作成します。実装しなければならないメソッドは GenerateCode だけです。GenerateCodeのinputFileContentパラメータに文字列でカスタムツールが設定されているファイルの内容がもらえますので、これを元にツールの出力を byte[] で返す事になります。 byte[] で返すので出力はテキストでなくてイメージファイルだったりなんかのバイナリでも構いません。逆にテキストを返す場合にはちゃんと出力の文字コードへのエンコード処理を記述しなければなりません。
続いて継承クラスを CodeGeneratorRegistrationAttribute で属性修飾します。同時に ComVisibleをtrue、 Guid属性、ProvideObject 属性で実体型を示す必要があります。

    [ComVisible(true)]
    [Guid("0E28FE58-1755-465E-A2D9-8B4AFD875742")]
    [CodeGeneratorRegistration(typeof(className), 
        "説明", 
        vsContextGuids.vsContextGuidVCSProject, 
        GeneratesDesignTimeSource = true)]
    [ProvideObject(typeof(className))]
    public class className : BaseCodeGeneratorWithSite
    {
        protected override byte[] GenerateCode(string inputFileContent) 
        {
            // ここでカスタムツール固有の実装をします。
        }
    }

実装しなければならないメソッドは単純に言えば string->byte[] ですので、単体テストプロジェクトから色々呼び出してテストしておくと最終工程で VS デバッガの中にVS読み込んでの確認をする必要性が減ってが楽になるんじゃないかなーとは思います。

デバッグと確認

単純にBuildしてデバッグしようとしても必要なレジストリ登録とか vsixインストール時に行われるべき事がされてない形になります、bin\Debug配下にvsixが出力されていますので vsix をインストールしてからデバッグ実行します。

デバッガから抜ける前に機能拡張マネージャからアンインストールを叩いておいたほうが良いでしょう。(もう一度 vsix インストールしようとしてダブルクリックすると「すでにインストールされています」で断られますので)

プロジェクトの種類は何でも構わないのでカスタムツールに渡すファイルを持つためのプロジェクトを作り、テキストファイルを作ります。カスタムツールを作成したカスタムツール名に設定してカスタムツールを実行でカスタムツールが実行されます。ブレークポイントを貼っていればブレークされるはずなので好きなだけデバッグしてください。(ただし、デバッガ内でVS起動するとCore2 Duo 2.8GHzでも起動するまでに30秒以上かかりますので、最後の統合レベルのデバッグ以外はデバッガ実行でのデバッグはおすすめできません。)

まとめ

実装そのものは部品がそろってれば比較的簡単でした。躓きどころはMEFでなくてCOMだっていう点、これについての注意事項はこの文書にすべて盛り込んだつもりです。MS提供のほとんど使える部品がそろってるのでそれをベースに淡々と組みましょう。

T4が AppDomainの分離とかで切り離されるとかの絡みで触れないインターフェース、サービスその他があるのに比べてこっちは比較的なんでも行ける感があります。T4のPreProcessor使って生成周りのコード作って呼ぶだけなら生成周りの実装も簡単と思いますので、T4のヘビーユーザーで深いVS Integrationを求める人は挑戦する価値はある素材だと思います。

Visual Studio 2010 後の世代のプログラミング(1) Code Contracts


Visual Studio 2010 「後」って事で VS2010 には正式には組み込まれてないんだけど、その後にリリースされた各種拡張がどんな感じでプログラミングに影響を与えるかの話。

(1)って事で連載。

 

というわけで最初は Code Contracts、Code Contracts については一回書いてるけど素晴らしく使える代物って事で導入から設定まで流した上で軽くイントロダクション

まずダウンロード、DevLabs Code Contracts から Download Standard Edition / Download Premium Edition どっちか選んでインストールする。僕は Premium を選んでインストールしたぜって事でそれをベースに書きます。

(ってか Static Checker 無いと契約違反をビルド時に検出できないんで魅力半減っていうより魅力なっしんぐ)

これをインストールするとプロジェクトのプロパティに Code Contracts にページが追加されます。追加されたページを通して一通りの設定をすると、Code Contracts による契約チェックが利用できます。

まず、デバッグ設定から、Static Checking のチェックを有効にして静的解析を有効にします。そして、Check in Background のチェックを外します。多少ビルド時間がかかる弊害があるっちゃあるのですが、ここにチェック入ってるとVisual Studio のエラーと警告の所に出ませんので、いくらチェックしても無駄です。

次に Release 設定、自分は以下をお勧めしてます。

Perform Runtime Contract Checking にチェック、ドロップダウンでは Precondition、Only Public Surface で公開部分の呼出しについてチェックを有効にします。

こんぐらいが実行時パフォーマンスに影響を与えず、本来 ArgumentExceptionが飛ぶべき時に飛んでくれるとかの最低限のラインだと思います。

んでオモムロにビルドすると CLR4 なプロジェクトでは結構色々警告されると思います。これは .NET Framework 4の各種アセンブリには Code Contracts の契約情報がデフォルトで埋め込まれてるので .NET Framework コンポーネントを普通に使ってるところで変なパラメータを渡してると契約にマッチしてないよと確認してもらえるからです。よーするにCode Contracts有効にしてる静的チェックを有効にすると ArgumentNullException が飛んでくるようなコードは警告が出ます。デバッガなんて必要ナッシング。

これが思わぬバグを見つける事は良くあります。

自分のバグは恥ずかしいので他人のバグという卑怯な振る舞いしますが WCF で XML-RPC を扱うサンプルを MS の中の人が書いているんですが ( XML-RPC with WCF (Updated) ) Code Contract が以下の部分を警告します。

class XmlRpcDataContractSerializationHelper . Serialize

                else if (valueType == typeof(Stream))
                {
                    int chunkSize = 1024 * 5;
                    byte[] buffer = new byte[chunkSize];
                    int offset = 0;
                    int bytesRead;
                    writer.WriteStartElement(XmlRpcProtocol.ByteArray);
                    do
                    {
// CodeContracts: requires unproven:  count <= (buffer.Length – offset)    
                        bytesRead = ((Stream)value).Read(buffer, offset, buffer.Length);     
                        writer.WriteBase64(buffer, 0, bytesRead);
                        offset += bytesRead;
                    }
                    while (bytesRead == buffer.Length);
                    writer.WriteEndElement();
                }

どんなバグかわかります?

よくやりがちなんですが、Stream.Read の offset パラメータは、ストリームのオフセットじゃなく、格納先バッファのオフセットです。これを間違えている事がこの警告の原因です。offset でなく0を与えればいいわけですね。(そうすると offset を誰も使いやしねーよって ReSharper が言ってくれるので、offset 変数とその操作をまるまる消す事でこのバグが解消します)

どう?すごいでしょ?僕はコードを動かしてテストでバグを探すなんて事を全くしてないわけです。でもバグを発見できるし直すこともできます。Code Contracts を有効にするだけでバグったコードを書くと警告してくれるわけです。いまデバッガ叩きながら必死にデバッグしてるそこのあなた!Code Contractsの静的解析通してみたら「そのバグの原因ここよ!」が一発でわかるかもしれませんですよ。

 

んで、Code Contracts を有効にするとフレームワーク呼出しのこの警告をまず消す事になるんですが、基本的には Contract.Assert で警告された事をまず書くだけで消えます。Contract.Assert( hoge!=null ); とかで null じゃない事を確認してあげれば良いわけです。これをやるときにあからさまにオカシイ事やってると普通の人は気付きますよね。これが Code Contractsの効果です。デバッグ版でテストを走らせれば該当部分を通ればきっと Assert されるでしょう。

Assertの場合には実際に確認のコードが生成されます。確認処理が重くなりかねない場合などは Contract.Assume を使う事でここではこうなってる「はず!」と言い聞かせる事ができ、これで警告は消えますが、その「はず!」が満たされてる事はテストなりなんなりでちゃんと確認した方が良いでしょうね。

もちろんパラメータで受け取ったものとかを AssertやAssumeするのはおかしな話で事前条件として Contract.Requires で書いた方がいいでしょう。

また、「var x = 自分で作ったメソッド(); FrameworkMethod(x) 」という風に自分のメソッドの戻り値を Contract.Ensure してあげれば良いわけですね。

という訳で Ensure が出てきました。戻り値に対する Contract.Ensure はちょっと特殊な書き方をします。

Contract.Ensures(Contract.Result<T>()!=null)

このように Contract.Result() に対して条件を記述します。Ensureはメソッド内のどこに書いても構いませんがメソッドからの戻り時にこの条件がチェックされます。

既存コードの警告つぶしをやってると大抵は Contract の書き方に慣れます、そこから interface に対する契約とか、設計での活用に進むと良いでしょう。

という訳で「僕と契約しないか?」な Code Contracts の紹介でした。次回は Contracts に絡めて Pex を使ってコードカバレッジの高いテストの自動生成です。

Visual Studio プロジェクトテンプレートの作り方


NuGet のプロジェクトテンプレートを公開してたりする人なので、レシピを公開しておきましょう。

最も簡単な方法は Visual Studio のファイルメニューからテンプレートの作成なんですが、今回はちっと難しい方法を。

Visual Studio SDK をインストールします。Download details: Visual Studio 2010 SDK

こいつをインストールすると、プロジェクトの種類として Extensibility が選べるようになり、Visual Studio の拡張パッケージを作成したり色々できる他に、その他色々のおまけがついてます。

image

今回は ASP.NET MVC3 のHttpModule を作成する為のプロジェクトテンプレートを書いてみます。プロジェクト名を設定して出てくる画面はこんな感じ。

image

いきなり vstemplate が開かれてますね。ソリューションエクスプローラーでの表示にはProjectTemplate.csproj 含め幾つかファイルが入ってますね。

というわけで、目的に応じて「あとは好きに致したまえ(ぇ」なんで、ASP.NET MVC3で使うHttpModuleの作成に使うテンプレートになるようにカスタムしていきます。

まず、Class1.cs で最初にできるべきコードを考える為に、本物を作ってみましょう。

クラスライブラリプロジェクトを追加して、そこの上で HttpModule を作るための作業をします。

image

System.Web とかを参照設定して

image

Class1.csをHttpModule1.csにリネームして IHttpModuleを派生して実装するのに十分な事をやります。

IHttpModule.DisposeのDisposeパターンを実装してやばそうなら Debug.Fail を呼ぶぐらいをデバッグ版でやるまでが今回想定できる範囲でしょうか。

image

ビルドしてちゃんとビルドできると解ったら、いきなり作ったクラスライブラリプロジェクトをアンロードします。

ソリューションエクスプローラーからプロジェクトのコンテキストメニューから「プロジェクトのアンロード」を選びます。

アンロードしたプロジェクトを右クリックで編集を選ぶと csproj の編集になります。(が見るだけで編集するわけではありません)

これを ProjectTemplate.csproj と並べたのがこんな感じ。

image

後はこの両者を比べながらProjectTemplate.csprojが「いい感じになるようにします(ぉぃ」ここでビルドシーケンスに仕込みとかができますね。NuGetパッケージプロジェクトの時はここで仕込みを入れました。(ちょっとだけ後述)

まぁ、参照設定の Reference の所が一番とっつき良いでしょうね。(MVC3入ってないじゃん、うん、裏でインストールやってて止まる罠にはまった為、単純にASP.NET HttpModuleのプロジェクトになってる)

いい感じになったらプロジェクトのコンテンツに行きましょう。

今回は HttpModule1.cs がコンテンツになりますのでコンテンツになるようにまた左右に並べて「いい感じになるようにします(ぉぃ」

image

こんな感じに。

$safeprojectname$ とかの暗号めいた物のリファレンスはこちら。

テンプレート名 ($if$ とかのドキュメントが無いように感じるのは自分だけでしょうか?)

お気づきかもですが、 NuGet の Configuration File and Source-Code Transformations がこの $で記号を挟む形式って事で、NuGetはVS内にあるテンプレート機構にオンラインリポジトリを結びつけた物という見方も出来たりするかもしれませんね。

んでこれをビルドするとプロジェクトテンプレートの zip ファイルが bin/構成 配下に吐き出されます。

これを自分の ドキュメントの Visual Studio 2010\Templates 配下の適切な場所に配置するとそれをベースとしてプロジェクトを作る事ができるようになります。

もともとビルド成功してた物を参考に「いい感じになるようにします(ぉぃ」だったので、プロジェクトを作ってみてビルドできない様であればなんかが間違ってるって事ですね。

csprojでのビルドシーケンスへの仕込みをする時の Tips

Visual Studio は結構激しく csproj と関連依存ファイルをキャッシュするので、csprojへの仕込みとデバッグは大変です。MSBuildのImportを使って分離した編集用ファイルを見るようにしておいてそれを編集しながらビルドを試すとかはこのキャッシュ機構によって、いくら編集して保存しても反映されない事になり「直したのに直らない→何がわるいのか解らない→挫折しちゃってもいいかなモードがひたすら上昇」の負帰還ループにはまります。

「csprojへの仕込みのデバッグは Visual Studio ではできない」これを最初に前提として進みましょう。

プロジェクトのアンロードをして csproj の編集に入ったら、スタートメニューから Visual Studio のコマンドプロンプトを開き、cd プロジェクトのフォルダで msbuild をコマンドプロンプトから叩けるようにしておいて(これをやってくれるVS拡張は色々あります) csproj を編集して保存したらビルドはコマンドプロンプトから実行します。ビルドがいい感じでできるようになるまではこの状況で進むのがおすすめです。

csproj内では msbuild のTaskやTargetを書く事になりますが、Visual Studio 2010 では MsBuild 4.0 の BeforeTarget/AfterTargetによって既存の Microsoft.Common.Tagets に手を入れずにシーケンスの途中に割り込めるようになりました。この機能の効果は結構絶大で MsBuild インラインタスクとかと組み合わせるとビルドシーケンスは結構思うがままです。(参考: MsBuild 4.0の新機能でビルド時コード生成とか)

注意事項ですが最終的にいい感じな csproj を作ったらテキストの複製を取って Visual Studio に csproj を再読み込みさせてすぐにアンロードして再度編集に入って比較するのがおすすめです。Visual Studioは自分に都合の悪い記述をデフォルト値に戻す動きを暗黙にやります。このようなVisual Studioによって削除されたりデフォルト値に戻された値についてはVisual Studioでのビルド、デバッグに支障がでない何らかの方策を実施する必要な項目として重要な情報ですが比較してみないことには解らないというのが結構厄介です。(この動作についてはMsBuild とVSの連携に関するところにドキュメントで書いてあった記憶はありますが見つからない…)

作ったプロジェクトテンプレートを NuGet 配布しちゃうぞ

って手前味噌ですが、自分の流した NuGetPackageProject を取ってください、とり方はNuGet パッケージプロジェクトテンプレートを参照。

するとNuGetパッケージの為のプロジェクトを作れます、これを作ってるソリューションに追加します。

image

プロジェクトテンプレートプロジェクトの出力、今回は bin\Debug\ に作成されている Mvc3HttpModuleProject.zip を Tools 配下に置くようにします。

今回はパッケージプロジェクトのビルド前イベントでcopy コマンドを使いました。

image

Package/content 配下に readme.htm を作ります。(本来的にはいらないんですが、何もないとinstall.ps1が動かないので)

image image

ソリューション配下の packages\NuGetPackageProject\Tools\install.ps1 からプロジェクトテンプレートへのコピー操作を取ってきて Package\Tools\install.ps1 に貼り付けます。(うわ、install.ps1が動かねーってデバッグしてた時のまんまになってる)

param($installPath, $toolsPath, $package, $project)

Copy-Item $toolsPath\*.zip -destination ([System.Environment]::ExpandEnvironmentVariables("%VisualStudioDir%\Templates\ProjectTemplates\Visual C#\"))Write-Host "Project Template installed"

って感じでどうでしょう。

NuGetPackage.tt を編集して好みの nuspec を書いてビルドすると貴方のプロジェクトテンプレートを配布する nupkg がめでたく出来上がったはずです。

ローカルリポジトリを使ってテストして後は nuget.org に流すだけです。アカウントとってアカウント承認してもらったらさっくり放流です。

ローカルリポジトリからの一連のあたりは neue cc – NuGetパッケージの作り方、或いはXmlエディタとしてのVisual Studio が詳しく書いてるのでそちらをどうぞ。

という訳で Visual Studio プロジェクトテンプレートの作り方からcsprojへの仕込み tips 、手前味噌の NuGet パッケージ作成の仕方でした。

MsBuild 4.0の新機能でビルド時コード生成とか


MsBuild 4.0 には結構良い新機能が入っております。

ここんとこツイッターでモニョモニョ言ってる MsBuild インラインタスクとか。

MsBuild ターゲット

  • RunBeforeTargets および RunAfterTargets (MSBuild 4.0)

(原文ママ、スキーマ見た感じでは BeforeTargets / AfterTargets が正しい)

これを使って TFS ビルド中にバージョンを埋めるタスクを作りましたのでおすそ分け

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build"
         xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <UsingTask
      TaskName="CreateAssemblyVersionSource"
      TaskFactory="CodeTaskFactory"
      AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll" >
    <ParameterGroup>
      <Path ParameterType="System.String" Required="true" />
      <VersionAndRevision ParameterType="System.String" Required="true" />
      <BuildUri ParameterType="System.String" Required="true"  />
    </ParameterGroup>
    <Task>
      <Code Type="Fragment" Language="cs">
<![CDATA[
        string buildNumber = new Uri( BuildUri ).Segments.Last();

        Log.LogMessage( "CreateAssemblyVersionSource Path: {0}",Path );
        StringBuilder sb = new StringBuilder();
        sb.AppendLine( "using System;" );
        sb.AppendLine( "using System.Reflection;" );
        sb.AppendLine( "using System.Runtime.InteropServices;" );
        sb.AppendLine( "using System.Resources;" );
        sb.AppendFormat( "[assembly: AssemblyVersion(\"{0}.{1}\")]"            ,VersionAndRevision, buildNumber ).AppendLine();
        sb.AppendFormat( "[assembly: AssemblyFileVersion(\"{0}.{1}\")]"            ,VersionAndRevision,buildNumber ).AppendLine();
        File.WriteAllText( Path, sb.ToString() );
]]>
      </Code>
    </Task>
  </UsingTask>

  <Target Name="LabelAssembly" Condition="'$(BuildUri)'!=''"
          AfterTargets="PreBuildEvent" BeforeTargets="CoreCompile"  >
    <Message Text="LabelAssembly target running" />

    <CreateAssemblyVersionSource
        Path="AssemblyVersion.cs"
        VersionAndRevision="$(VersionAndRevision)"
        BuildUri="$(BuildUri)" />

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

  </Target>
</Project>

やっている事としては結構単純で、 File.WriteAllText で cs ファイルを吐きだす事の AssemblyVersion / AssemblyFileVersion アセンブリ属性を。

それを Compile ItemGroup にInclueしてるだけです。

TFSビルド時には BuildUri にビルドの識別Uriがきますので、これがある時だけターゲットを定義するように Condition しており。

AfterTargets/BeforeTargets を使って CoreCompile ターゲットの前に実行される様に設定しています。

AfterTargets/BeforeTargetsによって関連するターゲットには何も変更を入れる必要がなくターゲットを差し込む事ができるというのが素晴らしい所でございます。

<PropertyGroup>

<VersionAndRevision>1.0.0</VersionAndRevision>

</PropertyGroup>

<Import Project=”ターゲットを保存した場所”/>

をcsprojの末尾でやるとTFSでのビルド番号がバージョンに反映されます。

このインラインタスクでやってる StringBuilder での編集をT4でPreprocessorしたテンプレートによって ITask実装しておくと、ビルドシーケンス中でのコード生成はもはやお手の物って訳で、組み合わせ次第で夢が広がりますねーなお話。

MSの中の人には MsBuild 4.0 関連の情報を MSDN Library のメニューにマージして頂きたいとか…。

TIPS: Visual Studio 2010のHTMLの改行規則を変更する


デフォルトだと p タグの中身まで前後で改行されたりして結構だらだら長いHTMLになってしまってカッコ悪い。

 

ツールのオプションからテキストエディターのHTML、タグ指定オプションを変更する。

20101111133625

20101111133936

クライアントHTMLタグの配下になぜかpが無いので「新しいタグ」からpを追加して改行を「前後」にする。

20101111134103

デフォルトは「開始タグの前と内部、および終了タグの後」となっている。

brもなぜか無いんだが、これは「タグの後」で改行するように設定するとすごく見やすくなる。

 

li とか、基本的に中身が単純な物とかは改行を「前後」にした方が基本として見やすいHTMLになると思うよ。

各タグの色付けなんか替えるとコードの表示もカラフルになるんで、気にしたくないタグをグレーにするとかするのも結構便利。お試し頂きたい。

 

設定変えたら、編集メニューから、詳細、ドキュメントのフォーマットで一気に適用だ!

ではでは、きれいなHTML書こうぜ!

VS2010 に機能拡張を入れると起動に時間がかかるようになる


なんかVS2010の起動に3分ぐらいかかるんですよ、おかしいなーと思って色々見て回った結果なんですが

 

vsix

ごめんなさい、ごめんなさい。スクロールバーのサイズみた時点で何が原因かよく解りましたですよ。