0. 前書き
Windowsデスクトップアプリケーションの配布・インストールの手段はいくつかあると思います。
・インストーラーをユーザーに渡し(例えば、配布サイトからダウンロードしてもらい)、インストールしてもらう
・ClickOnceを使ってアプリを配布する
⇒ClickOnceの詳細については、「ClickOnce 情報のサイト」を参照してください。
ClickOnceはWebとデスクトップを融合するという命題のもと.NET Framework 2.0で登場し、すでに10年間使われている枯れた技術と言えます。枯れた技術っていうのも良いですが、より優れた配布手段が考えられないかということで、今回紹介する「Squirrel.Windows」がOSSで開発されています。
1. Squirrel.Windows1とは
Squirrel.Windows(Github:Squirrel.Windows)とは、Windowsデスクトップアプリケーションの配布・インストール・アップデートの機能を提供するライブラリーです。これを適用すると、イメージとして、Google Chromeのようなサイレントアップデートの機能をデスクトップアプリに搭載することができます。
上述のサイトでは、Squirrel.Windowsの特徴を次のように説明しています。
Integrating : an app to use Squirrel should be extremely easy, provide a client API, and be developer friendly.
Packaging : is really easy, can be automated, and supports delta update packages.
Distributing : should be straightforward, use simple HTTP updates, and provide multiple "channels" (a-la Chrome Dev/Beta/Release).
Installing : is Wizard-Free™, with no UAC dialogs, does not require reboot, and is .NET Framework friendly.
Updating : is in the background, doesn't interrupt the user, and does not require a reboot.
今回は、Amazon S3をコンテンツ(バージョンアップ用のインストーラー)の配布元として、WPFアプリケーションを配布するまでを手順化してみようと思います。基本的には、Squirrel.WindowsのGetting-Startedをベースに進めますが、前述の通り配布元Amazon S3に変更したりしています。
2. 下準備
2-1. Squirrel化するアプリケーションを作成する
WPFのアプリケーションを作成します。
動作確認のためにアプリケーションに
・メッセージを出力する機能
・Exeファイルの置かれている場所を表示する機能
・バージョン番号を表示する機能
を載せることとします。
using System.Reflection;
using System.Windows;
namespace MyWpfAppForSquirrel
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var assembly = Assembly.GetExecutingAssembly();
//Exeの場所を表示
exeTextBox.Text = assembly.Location;
//バージョン番号を表示
versionTextBox.Text = assembly.GetName().Version.ToString();
}
}
}
バージョン番号の情報は、AssemblyInfo.csファイルに記載します。
[assembly: AssemblyVersion("1.0.0.0")]
このままVisual StudioでF5で実行すると、見た目は下記のようになります。
2-2. 配布元のAmazon S3を用意する
Amazon S3のウェブサイトホスティングの機能を使うため、ファイルを置いて、HTTPでアクセスできるように設定します。
設定方法は、AWSのチュートリアル等を参考にしてください⇒「例: 静的ウェブサイトをセットアップする」
作成したサイトのURLは
http://squirrel-windows-sample.s3-website-ap-northeast-1.amazonaws.com/
とします。
2-3. Nuget Package Explorerをインストールする
Squirrelはアプリケーションを配布するためにnugetのパッケージング技術を使います。
移行の手順で利用するので、インストールしてください。
https://npe.codeplex.com/
3. さっそく使ってみる
3-1. Integrating(統合)
2-1で準備したアプリケーションにSquirrelの機能を追加します。
まずは、nugetでSquirrel.Windowsをインストールします。
つづいて、アプリケーション起動時に、アプリケーションの更新処理をさせるために、App.xaml.csに処理を記述します。
(この記述がどのような動きになるかは、3-5で確認します)
using Squirrel;
using System.Threading.Tasks;
using System.Windows;
namespace MyWpfAppForSquirrel
{
public partial class App : Application
{
public App()
{
Task.Run(async () =>
{
using (var manager = new UpdateManager("http://squirrel-windows-sample.s3-website-ap-northeast-1.amazonaws.com/"))
{
await manager.UpdateApp();
}
});
}
}
}
3-2. Packaging(パッケージング)
最初の配布用にアプリケーションをパッケージ化します。
リリースビルドをする
Visual Studioで「Release」モードでアプリケーションをビルドします。
配布用パッケージのメタデータを作る
NuGet Package Explorerを用いて、NuGet Package fileを作成します。
NuGet Package Explorerを立ち上げ、「Create a new package」を選択します。
1.左ペインでメタデータを編集
「Edit Metadata」をクリックし、IDなどを編集
2.右ペインでパッケージングするモジュールを登録
・Add Lib Folder
・Add .NET folder ⇒ v4.5
・ビルド結果のファイル(dll、exe、exe.config、xml等)をドラッグ
3.NuGet Package fileを保存
名前を付けて保存(Save as...)を行い、「MyWpfAppForSquirrel.1.0.0.nupkg」という名前でソリューション(.sln)ファイルと同じ階層に保存します。
配布用パッケージを作る
Suirrel.exeを利用し、配布用パッケージを作成します。
再びVisual Studioに戻り「パッケージマネージャーコンソール」を開く。
次のコマンドを実行23。
ps1
PM> Squirrel --releasify MyWpfAppForSquirrel.1.0.0.nupkg
これで、「<solution-root>\Releases」フォルダの下に、配布用パッケージができました。
3-3. Distributing(配布)と、Installing(インストール)と、初回の起動
初回の配布は今回は何かしらの方法でダウンロードしたというシナリオにします。
上述のReleasesフォルダの中にある「Setup.exe」を実行します。
これでインストールが行われ、アプリケーションが起動します。
スクリーンショット中の「EXEの場所」からもわかるように、さきほどのインストールにより「%LocalAppData%\MyWpfAppForSquirrel」というフォルダが作成され、その中にバージョン番号ごとにフォルダが作られアプリケーションが配置されます。さらにOSにアプリケーションとして登録されるため、スタートメニューの「最近追加されたもの」にも表示されます。
3-4. アプリケーションのバージョンアップと配布準備
ここからが本題です。2回目以降のアプリケーションのバージョンアップ時に、「サイレントインストール」を実現させます。
アプリケーションのバージョンアップ
まずはアプリケーションをバージョンアップします。
・画面のメッセージ出力を変更します。
「Ver 1.1のアプリケーションです。」と変更しました。
・バージョン番号を、1.1.0.0に変更します。
[assembly: AssemblyVersion("1.1.0.0")]
ビルドする
バージョンアップしたアプリケーションを、再び「Release」モードでビルドします。
配布用パッケージのメタデータを作る
3-2と同じ手順で、NuGet Package Explorerを用いて配布用パッケージのメタデータを作成します。
・メタデータ ⇒ Version:1.1.0に変更
・保存する際のファイル名 ⇒ MyWpfAppForSquirrel.1.1.0.nupkg
配布用パッケージを作る
3-2と同じ手順で、配布用パッケージを作成します。
PM> Squirrel --releasify MyWpfAppForSquirrel.1.1.0.nupkg
上のスクリプトを流すと「MyWpfAppForSquirrel.1.1.0-delta.nupkg」というファイルが作成されていることが分かります。
このファイルが最初のバージョンとの差分を表現します。
配布用パッケージを配置する
更新されたReleasesフォルダの中身をAmazon S3に配置します。
(MyWpfAppForSquirrel-1.1.0-full.nupkgは不要です。)
以上で、配布の準備は完了です。
3-5. Updating(更新)
すでに3-3で端末にインストール済みのアプリを起動します。
見た目に変化はありません。3-3と同じアプリケーションが起動します。
ただこの時点で裏側で下記の仕組みが動きこっそりとアプリケーションのバージョンアップの準備が行われます。
- UpdateManagerがAmazon S3から更新用のモジュールを取得
- 「%LocalAppData%\MyWpfAppForSquirrel」に「app-1.1.0」が作成され、モジュールが展開
いったんアプリケーションを閉じて、もう1度アプリケーションを起動します。
そうすると、下記のようにアプリケーションがバージョンアップされていることが分かります。
4. おわりに
Squirrel.Windowsを利用すると、アプリケーションのサイレントアップデートが可能になることが分かりました。
検証できなかったですが、下記のポイントは柔軟で良さそうです。
・配布の方法
⇒ Webサイドから配布しなくても、ファイルサーバーとかでももちろんOK。
・「Check for update」みたな機能も作れそう
⇒ 別にサイレントインストールにしなくても、ユーザー駆動で更新モジュールを取得するといった機能も作れそうです。
ただこの手順はいまいちですね。手作業が多すぎるので、もう少し自動化できるようにしたいです。特に、NuGet Package fileを作成する箇所。
5. 参考
dotnetConf 2015のChannel9で、作者がデモを行っています
Squirrel for Windows - installing .NET apps the way it should be