あとはよしなに -2ページ目

ClickOnceプログラミング 其の五

ClickOnceプログラミング 其の五 「ノータッチデプロイメントとClickOnce」


だいぶ間が空いちゃいました。


今回のエントリは『「ノータッチデプロイメント」と「ClickOnce」どちらがいいの?』ということを扱います。

ちょっと短めのエントリです。

絵がない?何ですか、それ。食べられますか?


Web上の質問掲示板などでこんな書き込みを何回か見たことがあります。


・ClickOnceとノータッチデプロイメントはどっちがいいの?

これは自信を持って『「ClickOnce」のほうがいい』といえます。理由は後ほど。


・.NET Framework 1.1で作ったノータッチデプロイメントをClickOnceに移行すべきですか?

移行すべきだと思います。.NET Framework 2.0以降に移行予定なら。

というのも、「.NET Framework 1.1から2.0への移行」と「ノータッチデプロイメントからClickOnceへの移行」はその難易度が全然違います。マイグレーションと技術の変更という根本が違っちゃうからです。

ですから.NET Framework 1.1から2.0への移行という難易度の高い作業を完遂できるのであれば、ClickOnceへの移行なんておまけでできます。だってアプリケーションいじらなくていいもん。


証明書用意して、発行ボタンを押すだけ。


これだけでClickOnce発行ができ、これだけでノータッチデプロイメントの「Timestampに依存する差分ダウンロード」からClickOnceの「メッセージダイジェストに依存する差分ダウンロード」に移行できるんです。

ん?「色々ある機能使ってないけどいいのか?」って?

だってノータッチデプロイメントにはこういう機能ないじゃないですか(ダウンロードグループっぽい機能はあるけど)。ダウンロードグループとかHTTP圧縮とかデータファイルへの対応は、もう『機能拡張』の域にあるのですから、別にやらなくても問題ないはず。やればより良いですけどね^-^

あと必要な作業はお客さんに「前までのアプリケーション捨てて」って言うだけだと思います。


実はこの裏で色々機能の可能性が拡張されています。

これがClickOnceのほうがいいという理由ですね。

こっそり拡張されている機能を説明して今回は終わり。


■起動引数を安心して使えるようになる。

ノータッチデプロイメントでも起動引数は使えます。でも使えるからと言ってノータッチデプロイメントと起動引数を組み合わせちゃうと、アプリケーションの更新時にばぐっちゃうこともあるんですよ。

ノータッチデプロイメント(起動引数あり)をダウンロード中のHTTP通信を覗いてみると、なんだかおかしなことになってるのが分かるはずです。exe.configあたりがもう大変なことになってるはず。


■アプリケーションロールバックが利用可能になる。

これはClickOnceの基本機能ですね。

ノータッチデプロイメントはIEのキャッシュとして動作するものですから、アプリケーションの更新はアプリケーションファイルの上書きを意味します。元に戻すことはできないんですよ。


■アプリケーションをオフライン起動できるようになる。

ClickOnceをインストールモードで発行することで、アプリケーションをオフラインで利用できるようになります。営業さん向けのアプリケーションなんかはオフラインで起動できるといいですよね。

んじゃ、ノータッチデプロイメントはオフライン起動できないのか?といわれれば「できます。が・・・」という答え。

いや、IEをオフライン起動すればノータッチデプロイメントもオフライン起動しますが、、、そんな面倒なオペレーション誰がするんですか。

ITの仕組みが分からない人に「IEをオフライン起動しろ」っていうのは酷ですし・・・。IT業種ではないお客さんに「それくらい分かれ」なんていうのはお門違いですもんね。


■HTTP圧縮の可能性が広がる

通信トラフィック半分くらいですよ?(当社比)

ちなみに圧縮してるはずなのにWebサーバのCPU使用率も抑えることができます。

この内容については次回で扱うので、ここではあまり言いませんー。


■コードアクセスセキュリティの壁を突破できる

ノータッチデプロイメントは本当にコードアクセスセキュリティとの戦いです。

サーバ名にピリオドがあるようなサーバにアクセスすればインターネットゾーンという認識になります。

IPアドレスを指定してアクセスしたり、DNS登録されているサーバにアクセスすればもうインターネットゾーンですよ。こうなったらもう何もできません。

「ファイル書き込み?」「別のWebサーバへのWebサービス呼び出し?」「リフレクション?」もう全部ダメです。

ClickOnceでは必要な権限を昇格させることができるので、「もうどうしようもない!」というときに容易な回避策を取れます。あ、ちなみに「とりあえず完全信頼で発行しておこう」案はあまりお勧めしません。。。


これだけいいこと尽くめのClickOnce、使わない手はないでしょ?


あ、ちなみに「せっかくClickOnceに移行したんだから色々機能を追加しよう」って言い出すとデスマーチに突入しちゃうかもしれませんよ。ClickOnceは意外に奥が深いですし、機能を作りこむためにはソースコードへの修正が必要ですし、何よりテストしづらいですから。


次回でClickOnce関連の話は終わり。

次、何書こうかなぁ。

ClickOnceプログラミング 其の四

ClickOnceプログラミング 其の弐 「CDからのインストールとダウンロードグループ設定」


今回は「ダウンロードグループ設定」と「CDからのインストール」を併用した場合の注意点について考えてみます。


そもそも、これら2つの機能は何のために使うのでしょうか?

まずはそこから整理してみます。


1.ダウンロードグループ設定


ダウンロードグループは、遅延ダウンロードのための機能です。

ClickOnceアプリケーションがはじめてクライアントにロードされたとき、ダウンロードグループに紐付けられたファイルはまだクライアントにありません。


1.1. ダウンロードグループをダウンロードする


プログラム側から初めて呼び出されると通信が開始し、ファイルがクライアントにダウンロードされます。
プログラムから呼ぶ方法は以下のようなコード。

#ClickOnceアプリケーションとして起動しているかのチェックコードは省略しています。


ApplicationDeployment deploy = ApplicationDeployment.CurrentDeployment;
if (!deploy.IsFileGroupDownloaded(groupName))

{
  deploy.DownloadFileGroup(groupName);
}


さて。

これで完璧♪なんて言ってると、実行時にFileNotFoundExceptionが発生するので注意してください。


Windowsアプリケーションはアセンブリやファイルがすでにクライアントにあるものとして作業を進めます。

でも実はクライアントはサーバからファイルをダウンロードしている最中なのです・・・。


通信トラフィックが全てクライアントに届き、一時ファイルがClickOnceキャッシュ領域にコピーされるまではFileNotFoundExceptionが発生する可能性がありますのでご注意を。
#回避はインライン展開を防いだり、AssemblyResolveイベントの処理になりますが、ここでは割愛します^-^;

なんでこんな大事そうなことをさっくり割愛したか。


それはダウンロードグループのサイジングを伝えたかったからです。

次に移りましょう。


1.2. ダウンロードグループのサイジング


ダウンロードグループはファイルのグループです。

このサイズは自由気ままに決めてしまっていいのでしょうか?


答えは「あんまり良くない」です。


ダウンロードグループの割り当てられたファイルが2回目に呼び出されたときを考えてみましょう。

このときはファイルはすでにクライアントにあるので、通信をせずに利用できます。


じゃあ、アプリケーションのVer.1.0.0.0のときにクライアントにダウンロードしたグループのファイルは、

Ver.1.0.0.1のアプリケーションにはちゃんとあるでしょうか?


答えは、「ダウンロードグループを呼び出し済かどうかに依存する」です。


ダウンロードグループをプログラムからコール済ならば、Ver.1.0.0.1にちゃんと残っています。

ダウンロードグループをプログラムから未コールならば、Ver.1.0.0.1はこのグループのファイルを持っていません。
あとはよしなに-download
呼ばれた際に差分ダウンロード機能を使って、Ver1.0.0.1の領域に生成されます。


差分ダウンロード機能は、「ClickOnceキャッシュ領域の同じメッセージダイジェスト値を持つファイル」を探す機能ですので、この仕組みは理解できますよね。


んじゃ、差分ダウンロードでどのくらい昔のものまで見てくれるの?

クライアントロールバック機能実現のためにClickOnceキャッシュ領域に1世代を保持してくれていますので、

差分ダウンロード機能が有効に働くのは2世代前のバージョンまでです。


ちなみに、2世代前のファイルはアップデート直後に消えてなくなりますから、ダウンロードグループを利用する場合に差分ダウンロード機能を利用できるのは1世代前までです@w@;


ですので、ここまでくればもうお分かりのように、

ダウンロードグループ機能を細かくしすぎると、運悪く「2世代の間全く使われなかったグループ」はクライアントから消え去ってしまいます。

次回利用時には再度ダウンロードががががが・・・。


でもダウンロードグループを大きくしすぎると、、、ネットワーク負荷が上がっちゃうので、せっかく組み込んだ通信トラフィック分散のための考慮が無駄になっちゃう。


今のところ、グループの大きさは「機能1つ分」がいいと思っています。

実際にはさらに「権限制御」つまりAutholizationとの整合を考えてサイジングしていかないといけません。


2.CDからのインストール


んじゃ、今度はClickOnceアプリケーションをCDからダウンロードしてみましょう。


「やり方をお教えします」と初回に言ってあったのですが、実際言うと

そんなに難しい点はない・・・。


[手順:英語版Visual Studioでやっています]

A. プロジェクトのプロパティからPublishを選択する。

B. Publishing Folder Locationに「C:\tmp」などを指定する。

C. Installation Folder URLをClickOnceサーバのURLに設定する。

これだけです・・・。


やってみてもらえるとあまりに簡単すぎてあっけに取られちゃうと思います。


できあがったファイルをiso形式に変換して、それをCDに焼いてあげると、ClickOnce初期配布用のCDが出来上がります^-^


ちなみにAutorunはVisual Studio 2005のときはうまく動作しませんでした。

確か文字コードの関係だったと思いますが、Visual Studio 2008で試していないのと、昔の記憶なので忘れました・・・@w@

うまく動作させるためには自力で文字コードを変えてあげる必要があります。


手順は簡単なのですが、ここでも注意点はあります。

これはダウンロードグループとの連携がある際に注意点となることですからセクションを新しく設定して説明しましょう。


3.CDからのインストールとダウンロードグループ

「CDからのインストール」は「初回インストールは通信トラフィックがえらいことになること」に対処したいために利用する機能です。

「ダウンロードグループ」は主に「全部のファイルを同時にダウンロードしちゃうと通信トラフィックがえらいことになること」に対処したいために利用する機能です。


両方とも通信トラフィックを気にした場合にお世話になることが多そうです。一部のネットワークが64Kなんて細いところがあって不安なんていうシナリオだと飛びついて利用しちゃいそうです。


でもでも、「CDからのインストール」と「ダウンロードグループ」を併用すると、想像と違った動きをされちゃうことがあります。


これは.NET FrameworkおよびClickOnceローダが、「CDからインストールしていると認識している」わけではなく、「CDをサーバだと思い込んでいる」からです。


ですから、ダウンロードグループも呼び出されるまではクライアントにダウンロードされません!

CDからのインストールなのに、ダウンロードグループのファイルはインストールされないのです^-^;

うへぇ。


このため、ClickOnceアプリケーションをCDとして発行するつもりなら、ダウンロードグループ機能は一部を残して全て解除すべきです。

一部とは、「管理者しか使わない機能」をまとめたグループは一般ユーザのマシンには入れないほうがいいでしょうから、これだけ除外しましょうということです。


あれ。でも、CDからインストールしないユーザもいるんですよね?


直接サーバにアクセスしてくるユーザに対してダウンロードグループを設定していなかったら、通信トラフィックが祭り状態になってしまいます。


CDからインストールしたユーザにはグループほぼ全部を一気にインストールしたい!

インターネット経由でインストールしたユーザにはグループをダウンロードさせたくない!


なんていうわがまま^-^;

でもこれは簡単に解決できます。


回避は以下の方法で実施します。


1.CD用のアプリケーションを、ダウンロードグループ設定を解除した状態でVer1.0.0.0として発行し、CDに焼きつつ、IISに登録してしまう。

2.ダウンロードグループ設定を設定したClickOnceアプリケーションを何も変更しないでVer1.0.0.1としサーバに発行する。


これだけでうまくいきます。

アプリケーションを更新しなくてはならなくなった場合、CDはたぶん作り直さないと思うので、サーバだけ更新すればOKです。

#CD作り直すなら同じことを再度やってもらえればOKです。Ver1.1.0.0とVer1.1.0.1を用意するだけです。


ただ、これだけで「CDからインストールしたユーザ」の「ダウンロードグループの寿命」を1世代分縮めてしまっていますので、グループのサイジングには十分注意してくださいね。

運用まで見据えると「CDからのインストール」と「ダウンロードグループ」の併用は意外に難しいんですねぇ。


--------


今回のエントリは、読んだ人にちゃんと伝わる内容だったのでしょうか・・・?

書き始めた時点ですでに眠いという状況だっただけに不安・・・。絵もほとんど使ってないし・・・。

「絵使ってよ!」って言われたら足します・・・。

ClickOnceプログラミング 其の参

ClickOnceプログラミング 其の参 「データディレクトリの仕組みと利用アイデア」


今回は「データディレクトリ」について考えてみます。


1.データディレクトリとは。

そもそもデータディレクトリとは何なのかから説明します。

ClickOnceにはファイルを保存できる領域が2種類あります。

注) Vista以降の場合、パスが変わっていますので注意してくださいー。


ClickOnceキャッシュ領域

%userprofile%\LocalSetting\Apps\2.0


ClickOnceデータディレクトリ

%userprofile%\LocalSetting\Apps\2.0\Data

ClickOnceを発行すると、ファイルはデフォルトでClickOnceキャッシュ領域に格納されます。

ユーザが発行時にオプションを選択することでファイルはデータファイルとしてマークでき、

データファイルとしてマークしたファイルはClickOnceデータディレクトリに格納されることになります。


あとはよしなに-datafile

XMLファイルなど一部の形式のファイルは、デフォルトでデータファイルになるため、注意が必要です。


2.データディレクトリの不具合

※不具合といっても、バグではありません。適切に使えば、データディレクトリはうまく機能します。


データディレクトリには1つだけ困った特徴があります。

その特徴とは「データファイルは変更がなくとも、必ずダウンロードされる。」ということです。


これは、ネットワークトラフィックに制限がある案件では困ったことになります。

WEBを見ていると、データベースファイルやACCESSのファイルをデータファイルとしているのをよく見ますが、この方法は更新時に通信量がえらいことになっちゃうのでお勧めできないです;;


僕的にデータファイルは「ユーザがカスタマイズする」という範囲に留めるべきじゃないのかな?と思っています。

「キーコンフィグ」や「デザイン」をカスタマイズ可能にしてクライアントに保存する機能が必要な場合、データディレクトリを使うのがいいんでしょうね。


すみませんが、以下ではデータファイルに利用するのは、XMLファイルなどの小さなファイルとすることを前提にします。

データベースファイルやACCESSをデータファイルとしたいのであれば別の考慮を組み込むほうが良いですから・・・。


3.データディレクトリの仕様


それではデータディレクトリの仕様について。

※ここで述べるのはデータファイルがサーバで管理されている場合の話です。


XMLFileというXMLファイルをデータファイルとしてマークしてインストールしたとします。


すると、キャッシュ領域とデータディレクトリには以下のようにファイルが配置されます。

あとはよしなに-datadirectory

あれ?データファイルはデータディレクトリに配置されるんじゃないの?と思いそうですが、、、


実はClickOnceキャッシュ領域にあるファイルとデータディレクトリにあるファイルの役割は全然違います。

その役割は以下。


・ClickOnceキャッシュ領域にあるデータファイル

  サーバでデータファイルが変更されたかどうかを検知する。

・ClickOnceデータディレクトリ

  クライアントアプリケーションでファイル操作をする場合の対象ファイル。


サーバでアプリケーションが更新されたら?

前述の通り、データファイルがクライアントにダウンロードされます。


ダウンロードされたデータファイルは前バージョンのClickOnceキャッシュ領域にあるデータファイルと比較されます。比較結果に応じてデータディレクトリに配置されるデータファイルが異なります。

あ) 比較した結果、データファイルに変更がなかった場合

  前バージョンのデータディレクトリからデータファイルをコピーします。

い) 比較した結果、データファイルに変更があった場合

  新バージョンのデータファイルをデータディレクトリにコピーします。前バージョンのデータファイルは破棄します。


このため更新時にデータファイルを破棄したくない場合は、サーバでデータファイルを更新してはならなくなります。

まぁ、これはメジャーバージョンアップ時にデザインの仕様などを一新した場合などにいい仕組みかも。


でもでも、サーバでファイルを更新しないならサーバで管理する必要ないですね^-^;
サーバでデータファイルを管理せずにデータファイルをうまく扱う方法があればいいのですが・・・。

これについては次のセクションで。


4.データファイルと扱われる条件


データファイルが「データファイルと扱われる」条件を紹介します。


どういったファイルがデータファイルなのでしょうか?

実は以下の条件に当てはまるものは全てデータファイルとして扱われます。

・ファイルが「データファイル」としてマニフェストにマークされている。

・マニフェストで管理されていないファイルがデータディレクトリにある。
・user.config


一つずつ見てみます。

でも『ファイルが「データファイル」としてマニフェストにマークされている』は説明しませーん^-^


マニフェストで管理されていないファイルがデータディレクトリにある。


要はファイルがデータディレクトリにあれば、データファイルとして扱われるということです。

サーバでファイルが更新されることがないため、データファイルは破棄されることがありません。


じゃあ「どうやってデータディレクトリにファイルを置けばいいの?」という問題が出てきそうです。

何しろ、ClickOnceキャッシュ領域もデータディレクトリもランダム文字列を含むディレクトリですから、アクセスが大変そう・・・。


でも、実はすごくアクセスが簡単で、以下のコードで取得したパスにファイルを置けばいいんです。

※アプリケーションの単体テストなどを実現するため、アプリケーションがClickOnceとして管理されていない場合の制御は必ず入れる必要があります。この考慮をしていないと、単体テスト時に例外が出放題になります


if (!ApplicationDeployment.IsNetworkDeployed)
{
  return Application.StartupPath;
}

return ApplicationDeployment.CurrentDeployment.DataDirectory;


user.config

なんだか意味不明なこのConfigファイル。

これはapp.configにユーザスコープで定義したパラメータを定義するファイルのことです。

構成ファイル(app.config)にユーザスコープの変数を定義します(以下参照)。

<configuration>
<configSections>
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup・・・省略" >
<section name="WindowsFormsApplication2.Properties.Settings" ・・・省略/>
</sectionGroup>
</configSections>
<userSettings>
<WindowsFormsApplication2.Properties.Settings>
<setting name="Yoshinani" serializeAs="String">
<value>HogeHoge</value>
</setting>
</WindowsFormsApplication2.Properties.Settings>
</userSettings>
</configuration>


このYoshinaniという変数はユーザスコープで利用されるため、

プログラムからYoshinani変数を変更すればuser.configがデータディレクトリに生成され、以後データファイルとして扱われます。

Yoshinani変数にアクセスするときは、このuser.configにアクセスすることになるので、カスタマイズを実現することができます。

ちなみに、プログラムからYoshinani変数に一度もアクセスしない場合、user.configは生成されません。


変数の体系を変えたい場合はサーバ側のapp.configを操作すればOKです。

なお、user.configでは新バージョンで使わなくなる変数がクライアント側で消えないのがネックです。

まぁ旧変数にアクセスしなければいいですよね。無理やり削除してあげてもいいわけですg・・・(自粛



5.まとめ


データディレクトリは特に消えてもエンドユーザの業務に致命的なダメージを与えない、

ユーザの利便性向上のためのユーザカスタマイズを実現したい場合にぴったりです。


以下の理由により、消えてはならないデータをデータファイルとすべきではありません。

・データが破棄される可能性がある。

・ClickOnceアプリケーションをアンインストールすると消える。


アプリケーションログも必要に応じてデータファイルではない場所に保存するべきでしょう。

僕はよくCドライブ直下にディレクトリを作って、そこに置くようにしています。アンインストールで消えないことは先に顧客と握っています。

こういった場合、ユーザアカウント制御(UAC)には注意してくださいね。

何しろClickOnceアプリケーションを利用している場合、UACの権限昇格ダイアログを出すことができませんから。。。


さて。

ここから先はアイデア勝負です。

アイデアは要件に応じてカスタマイズしなくてはならないのでアイデアを例示することができません・・・。

ただ、データディレクトリとデータファイルの仕様が分かれば要件にあわせて、アイデアを考え出すのはそう難しくはないはずです。


ほら、適用範囲を絞ればデータディレクトリの不具合なんか、あまり気にならないですよね?^-^