Antoine.st Automatic Update

Automatic Update

配布対象がごく少数であれば、セットアップパッケージを作成してそれを動かすだけで OK です。ですが、配布対象が十数台を超えると、もう面倒。バージョンアップが合ったときなんて大変です。

そこで、検討対象となるのが自動更新機能。ノータッチデプロイメントとか ClickOnce などは言うまでもなく、Web アプリケーションも、そもそも配布の手間を減らすってのが大きな目的のひとつです。

この辺、割とありがちな機能なので、フレームワークで用意されていてもいいと思うんです。やることは簡単で、サーバー側のアプリケーションのバージョンを調べ、もしクライアントのものより新しければ更新、同じであればそのままにする、とそれだけです。

ただ、更新の頻度をどうするか、タイミングをどうするか、バージョンの確認をどうするか、自分自身を更新するときはどうするか、などがポイントになってきます。前に作ったときは、サーバーの共有ディレクトリにファイルを置いておく仕組みだったので、実行ファイルのバージョン情報をクライアントから読み取るようにしていました。ただし、これをやるとえらい時間がかかったので (64 K で接続された環境もあったから)、XML ファイルを置いておいて、それをダウンロード、読み取るように修正。タイミングは、アプリケーションを起動したときでした。

Functionality

この辺をいろいろ考慮して、必要な機能を考えていくことにしましょう。

UpdateMethod Property

Update、バージョンのチェック方法を指定する。HTTP、FTP、FileShare (Windows のファイル共有) などでしょうかね。

FileURL Property

ファイルを置いておく場所。ファイル共有でも URL? という疑問があったりなかったりしますが、ま、あまり気にしないでください。

IsNewerVersionByFileVersion() Method

対象となるファイルのバージョンでチェックを行う。使用可能なのは、UpdateMethod で FileShare が指定されているときのみ。わざわざダウンロードしてからチェックするってのもおかしな話ですからね。

CheckVersionByFileName() Method

対象となるファイルの名前でバージョンチェックを行う。これを利用するときは、機能名_x.xx.xxxx.exe というような名前にしておく必要がある。複数のバージョンを保持したいときとか便利かも。このメソッドを使うときは、HTTP でディレクトリリスティングができないと駄目ですね。

CheckVersionBySettingFile() Method

対象となるファイルの名前、バージョンが書かれた設定ファイルを使ってバージョンチェックを行う。設定ファイルは XML でしょうかね。やっぱり。CheckVersion 系のメソッドでは、True/False で処理の成功/不成功を示します。

CheckingProgress Event

チェックの途中経過を示すイベント。ファイル数と確認済みファイル数を返せばいいでしょうか。

IsNewerVersion Property

バージョンチェックの結果として、新しいバージョンのファイルがあれば True を返します。メソッドで直接返せないってのはちょっと嫌かも。

Details Property

チェック結果の詳細を示します。ファイル名、現在のバージョン、新しいバージョンを返せば十分でしょうかね。複数のファイルが含まれる可能性があるので、文字列の配列にしておきます。

DownloadFiles() Method

ファイルをダウンロードします。とりあえず、ダウンロードとアップデートは分けておくことにします。

DownloadProgress Event

ダウンロード中の経過って必要ですね。ファイル共有時はどうしましょうか。途中経過が出せるコピー方法ってかなり限られちゃいますが。

UpdateFiles() Method

UpdateFilesByReboot() Method

UpdateFilesByRestart() Method

Sample

使用例としては、以下のような感じになるでしょうか。


  bool updateSample() {

    AutomaticUpdate au = new AutomaticUpdate();

    au.UpdateMethod = UpdateMethods.HTTP;
    au.FileURL = "http://www.sample.com/";

    if (!au.CheckVersionBySettingFile()) {
      ShowErrors();
      return false;
    }

    if (!au.IsNewerVersion()) {
      return true;
    }

    ShowDetails(au.Details);

    if (!au.DownloadFiles()) {
      ShowErrors();
      return false;
    }

    if (!au.UpdateFiles()) {
      ShowErrors();
      return false;
    }

    return true;

  }