.NET TIPS

ClickOnceアプリをコマンドラインから発行するには?[2.0のみ、C#、VB]

デジタルアドバンテージ 一色 政彦
2006/10/13
2006/10/23 更新

 Visual Studio 2005(以降、VS 2005)で作成したClickOnceアプリケーション(以降、ClickOnceアプリ)の開発を自動化する際に、その発行も自動化したいというケースは多いだろう。というのも発行を行うたびにVS 2005のIDEを起動するのは面倒で無駄な作業だからだ。

 実際にこれを行う最もシンプルな方法は、次のように、コマンドラインから(.NET Framerowrk 2.0に付属する)ビルド・ツールMSBuild.exe(以降、MSBuild)を呼び出すことだ(コマンドラインの意味についてはコードの説明欄を参照されたい)。

set PATH=C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727;%PATH%
msbuild WindowsApplication1.csproj /t:Publish /p:Configuration=Release
MSBuildによるコマンドラインからのClickOnceアプリの発行
「WindowsApplication1.csproj」はVS 2005で作成したC#のプロジェクト・ファイルである。「/t」は、MSBuildのスイッチとして指定可能な「/target」(=Targetスイッチ)の省略形だ。また「/p」は「/property」(=Propertyスイッチ)の省略形で、ここではConfigurationプロパティ(=「構成」)を「Release」モードに設定している。
ちなみに、1行目の「set 〜」はMSBuild.exeへのパスを通す(=MSBuild.exeを呼び出し可能にしている)ためのコードである。
なお、TargetスイッチやMSBuildの使い方については、「.NETビルド・エンジン「MSBuild」使いこなし術」を参照してほしい。

 このコマンドラインでは、MSBuildを実行して、「WindowsApplication1.csproj」のプロジェクトをリリース・モードでPublish(発行)することを指定している。

 しかし、このコマンドラインを実行しても、実際には開発者が意図したとおりの動作を行ってくれない。具体的には、MSBuildファイル(この例ではWindowsApplication1.csprojファイル)で指定した発行先(具体的にはPublishUrlプロパティに指定したURLもしくはパス)に、ClickOnceアプリがコピーされない(=配置されない)のである。

 厳密にはClickOnceアプリは、(PublishUrlプロパティではなく)PublishDirプロパティで指定された場所に発行されている。このPublishDirプロパティに何も値が指定されなかった場合(通常は指定されない)、自動的に「$(OutputPath)$(AssemblyName).publish\」というパスに発行先が決定される。この「$(OutputPath)」はプログラムの出力先を表し、「$(AssemblyName)」はアセンブリ名を表すので、本稿の例では(プロジェクト・ディレクトリ配下の)「bin\Debug\WindowsApplication1.publish」というフォルダに発行されることになる(「$(<プロパティ名>)」という構文は、MSBuildで使われるプロパティの値を取得するための構文である。詳しくは「ビルド・エンジン『MSBuild』を思いのままに操る技」を参照してほしい)。この動作は、MSBuildとVS 2005のIDEのどちらによって発行した場合でも変わらない。

 問題は、この発行の後、VS 2005のIDEのみは独自にPublishUrlプロパティで指定されたURL(IIS)やパスに対して、発行されたClickOnceアプリの全内容をコピーすることである。この機能にMSBuildは対応していない。そのため、MSBuildは開発者が意図した動作を行ってくれないというわけである。

 それでは、MSBuildを使った場合も(VS 2005のIDEと同じように)、発行されたClickOnceアプリを発行先にコピーするにはどうすればよいのだろうか? これには主に2つの方法がある。

(1) MSBuildスクリプトを使ってコピーを行う
(2) PublishDirプロパティを指定して直接PublishUrlプロパティの場所に発行する

 以降ではこれらの方法をそれぞれ説明していくことにしよう。

(1) MSBuildスクリプトを使ってコピーを行う 

 まずは、MSBuildの機能によって、発行されたClickOnceアプリを、発行先(=PublishUrlプロパティの場所)にコピーする方法を紹介しよう。

 ただしここで示す方法では、VS 2005のIDEが搭載している「ローカルIIS上への配置」や「FTPによる配置」「FrontPage Server Extensions機能を活用した配置」は考慮しない(記述内容が巨大になってしまうため)。本稿では、単なるコピー作業(XCOPY)のみを行うMSBuildファイルの作成を説明する。

 それでは、既存のプロジェクト・ファイル(MSBuildファイル)に、次のコードを書き加えてほしい。

<Project>
……中略……
  <Target Name="CopyPublishedApplication">

    <!-- まずは発行フォルダ全体をコピーする -->

    <CreateProperty Value="$(ProjectDir)$(OutputPath)$(AssemblyName).publish">
      <Output TaskParameter="Value" PropertyName="_PublishSorcePath" />
    </CreateProperty>

    <CreateProperty Value="C:\Inetpub\wwwroot\$(AssemblyName)">
      <Output TaskParameter="Value" PropertyName="_PublishDestPath" />
    </CreateProperty>

    <Exec Command="xcopy &quot;$(_PublishSorcePath)&quot; &quot;$(_PublishDestPath)\&quot; /E /Y /I" />

    <!-- 次にバックアップ用の配置マニフェスト・ファイルをコピーする -->

    <FormatVersion Version="$(ApplicationVersion)" Revision="$(ApplicationRevision)" FormatType="Path">
      <Output TaskParameter="OutputVersion" PropertyName="_VersionFragment"/>
    </FormatVersion>

    <Exec Command="copy &quot;$(_PublishSorcePath)\$(AssemblyName).application&quot; &quot;$(_PublishDestPath)\$(AssemblyName)_$(_VersionFragment).application&quot; /Y" />

  </Target>
</Project>
既存のプロジェクト・ファイルに追記するコード
前述したが「$(<プロパティ名>)」という構文は、MSBuildで使われるプロパティの値を取得するための構文である。それぞれのプロパティの意味は次のとおりだ。
・$(OutputPath):プログラムの出力先
・$(AssemblyName):アセンブリ名
・$(ProjectDir):プロジェクト・ディレクトリ
・$(ApplicationVersion):アプリケーション・バージョン(基本的にリビジョン部分は含まない)
・$(ApplicationRevision):アプリケーション・バージョンのリビジョン部分(=一番右端の番号)
XMLファイルでは「"」(ダブルクォーテーション)は「&quot;」というエスケープ文字で表す。

 このコードでは「CopyPublishedApplication」という名前のターゲットを作成している。

 CopyPublishedApplicationターゲットの内容は、すでに発行されたClickOnceアプリ全体をコピーし、さらにバックアップ用のマニフェスト・ファイルをコピーするというものである(なお、バックアップ用の配置マニフェスト・ファイルとは、VS 2005のIDEで発行すると発行先にコピーする際に、「WindowsApplication1_1_0_0_1.application」のような形式の名前で自動生成されるファイルである。発行先にClickOnceアプリをコピーする際に生成されるものなので、当然ながらMSBuildによる発行ではこのファイルは生成されない)。

 もう少し細かく見ていくと、まず<CreateProperty>要素によって、コピー元パス名を取得するための_PublishSorcePathプロパティを、さらにコピー先パス名を取得するための_PublishDestPathプロパティを新規作成している(このプロパティの値は「C:\Inetpub\wwwroot\$(AssemblyName)」を指定している)。そして<Exec>要素によって、実際のClickOnceアプリのコピー処理(=配置)を実行している。

 次に<FormatVersion>要素によって、ClickOnceアプリの発行バージョン名を「1_0_0_1」のような形式に整形し、<Exec>要素で、コピー元のフォルダ内にある「WindowsApplication1.application」を「WindowsApplication1_1_0_0_1.application」のような名前のファイルとしてコピー先にコピーしている(当然ながら「1_0_0_1」の部分は実際の発行バージョンによって変化する)。

 以上のコードを追加したら、作成したCopyPublishedApplicationターゲットを、次の例のように、MSBuildから呼び出せばよいわけだ。

msbuild WindowsApplication1.csproj /t:Publish,CopyPublishedApplication /p:Configuration=Release
MSBuildでClickOnceアプリの発行後にCopyPublishedApplicationターゲットを呼び出す例

 この例で分かるように、/tスイッチはカンマ区切りで複数のターゲットを指定できる。この例では、Publishターゲット(=ClickOnceアプリの発行)の次に、CopyPublishedApplicationターゲット(=ClickOnceアプリの配置=発行したClickOnceアプリをコピー)を実行するように指定している。なお、ここで新規に追加したCopyPublishedApplicationターゲットはデフォルトのビルドでは呼び出されないため、VS 2005のIDEによるビルドや発行にはまったく影響しない。

(2) PublishDirプロパティを指定して直接PublishUrlプロパティの場所に発行する

 次にPublishDirプロパティを直接指定する方法だ。

 これを行うのにMSBuildファイルで直接PublishDirプロパティを指定してもよさそうだが、これはできない。PublishDirプロパティはVS 2005のIDEで発行する際にも使われるため、もし指定されたPublishDirプロパティが想定外の場所である場合(VS 2005のIDEは「$(ProjectDir)$(OutputPath)$(AssemblyName).publish」の場所にClickOnceアプリが発行されていることを想定している)、VS 2005でClickOnceアプリの配置(=発行したClickOnceアプリをコピー)に失敗してエラーとなってしまうからである。

 従ってこの方法を採用する場合、次の例のようにMSBuildのコマンドライン・オプションとしてPublishDirプロパティを指定する必要がある。

set PATH=C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727;%PATH%
msbuild WindowsApplication1.csproj /t:Publish /p:PublishDir="C:/Inetpub/wwwroot/WindowsApplication1/" /p:Configuration=Release
PublishDirプロパティを指定したMSBuildによるClickOnceアプリの発行
「/p」は、MSBuildのスイッチとして指定可能な「/property」(=Propertyスイッチ)の省略形だ。つまりこの例では、PublishDirプロパティに「C:/Inetpub/wwwroot/WindowsApplication1/」というパスを指定しているわけである。

 なお、このPublishDirプロパティの記述には以下のような注意点があり、慎重に行う必要がある。

  • IISには対応していない
    →例えば「http://localhost/WindowsApplication1/」のような発行先は指定できない。

  • “\”は使えず、すべて「/」で記述する必要がある
    →例えば「C:\Inetpub\wwwroot\WindowsApplication1\」は「C:/Inetpub/wwwroot/WindowsApplication1/」と記述する必要がある。

  • 最後に必ず“/”を含める必要がある
    →例えば「C:/Inetpub/wwwroot/WindowsApplication1」という記述はできず、「C:/Inetpub/wwwroot/WindowsApplication1/」のように最後に必ず“/”を含める必要がある。含めない場合、正しいフォルダ名/ファイル名で発行されない。

publish.htmファイルの生成について

 あと、コマンドラインからClickOnceアプリを発行する際に気にかかるのが、publish.htmファイルが生成されないことだ。しかし、実際にVS 2005が生成したpublish.htmファイルをそのままの形で正式な業務アプリケーションで使用することはあまりないのではないだろうか。

 従って、テンプレートとなる独自のHTMLファイルを作成し、発行後にそれをコピーして、そのテンプレートの一部(例えばアプリケーションのバージョン番号など)を何らかの手段で書き換えるような仕組みを構築すればよいだろう。例えば、MSBuildのターゲットを作成した本稿の(1)の例のような形で、テンプレートのHTMLファイルを発行先へコピーしてカスタマイズするような仕組みが考えられるだろう。End of Article

利用可能バージョン:.NET Framework 2.0のみ
カテゴリ:Windowsフォーム 処理対象:ClickOnce

この記事と関連性の高い別の.NET TIPS
難読化したアプリケーションをClickOnceで配布するには?
ClickOnceアプリケーションをデバッグするには?
多言語対応アプリケーションをClickOnceで配布するには?
ClickOnceアプリをロールバックさせるには?
GACコンポーネントをClickOnceで配布するには?
このリストは、(株)デジタルアドバンテージが開発した
自動関連記事探索システム Jigsaw(ジグソー) により自動抽出したものです。
generated by

「.NET TIPS」


更新履歴
【2006/10/23】本記事の一部に以下のような誤りがありました。お詫びして訂正させていただきます。

<Exec Command="xcopy &quot;$(_PublishSorcePath)&quot; &quot;$(_PublishDestPath)\&quot; /Y /I" />
<Exec Command="xcopy &quot;$(_PublishSorcePath)&quot; &quot;$(_PublishDestPath)\&quot; /E /Y /I" />


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 記事ランキング

本日 月間