TemplateFile タスクで ClickOnce の publish.html を用意する

MSBuild.Community.Tasks の TemplateFile を使ってみた - お だ のスペースMSBuild.Community.Tasks の TemplateFile を紹介しましたが、これを ClickOnce の publish.html の生成に使ってみようと思います。
publish.html は ClickOnce のスタートページ になる html です。Visual Studio から発行した際には、自動生成してくれるのですが、MSBuild で発行すると自動生成してくれません。
また、自動生成以外の html を使いたい場合も多いと思います。しかも、発行する際に変更する箇所といえば、バージョン番号だけだったりしませんか?
これは、TemplateFile タスクが使えそうな局面ですね。


ということで、プロジェクトファイルの一部を抜粋。
省略している部分は、プロジェクトに含むコードが記載されていたり、Visual Studio から ClickOnce の設定した際に追加される Bootstrapper だったりします。

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets" />
  …(省略)
  <ItemGroup>
    <None Include="publish.template" /> <!-- publish.html の雛型 -->
  </ItemGroup>
  <PropertyGroup Condition="$(PublishPath) != ''"> <!-- MSBuild から実行する時は、PublishPath プロパティに発行する値を渡す様にし、PublishDir を PublishPath と同じ値にする  -->
    <PublishDir>$(PublishPath)</PublishDir> 
  </PropertyGroup>
  <PropertyGroup Condition="$(PublishPath) == ''"> <!-- PublishPath に値が設定されていない場合、(Visual Studio からの発行を想定) PublishPath は PublishUrl と同じ値にする -->
    <PublishPath>$(PublishUrl)</PublishPath>
  </PropertyGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

  <ItemGroup>
    <TemplateToken Include="Version"> <!-- publish.template の ${Version} を ApplicationVersion の値で置き換える  -->
      <ReplacementValue>$(ApplicationVersion)</ReplacementValue>
    </TemplateToken>
  </ItemGroup>
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target>
  <Target Name="AfterPublish"> <!-- Publish タスクの後に走る -->
    <MakeDir Directories="$(PublishPath)" />
    <TemplateFile Template="$(MSBuildProjectDirectory)\Publish.template" OutputFileName="$(PublishPath)Publish.html" Tokens="@(TemplateToken)" />
  </Target>
</Project>

PublishPath、PublishDir、PublishUrl と似たようなのが幾つもあるのは、何かややこしい理由があるからです。
MSBuild で発行した際に配置される場所は PublishDir に指定した場所です。しかし、Visual Studio から発行する場合は、PublishUrl *1に発行されます。
しかも、Visual Studio から発行する際に、PublishDir を既定値以外の値*2を設定していると、発行エラーが発生します。
というわけで、MSBuildVisual Studio 両方から同じ様に発行するには、もう一つ変数(PublishPath)が欲しいなぁというのが理由です。


PublishDir の話しは、ClickOnceアプリをコマンドラインから発行するには?[2.0のみ、C#、VB] − @IT に載ってました。

*1:PublishUrl は Visual Studio で指定した発行する場所

*2:Microsoft.Common.targets で何かの値を設定している