久しぶりにClickOnceでC#アプリを作成・配信してみたらやり方を忘れていた部分があったため、メモを残しておきます。
環境
- Active Directory 環境構築済
- Active Directory 証明書サービス(AD CS) 環境構築済*1
- VisutalStudio 2012
アプリのアイコンの生成
自分でicoファイルを用意するか、VisualStudioでアイコンを作成します。VisualStudioで生成する手順は以下となります。
- プロジェクト > 新しい項目の追加 > アイコンファイル でアイコンファイルを生成
- プロジェクトのProperties > アプリケーションタブ > 生成したicoファイルを指定
参考:アプリケーションに独自のアイコンを設定するには? - @IT
発行バージョンの取得
ApplicationDeployment.CurrentDeployment.CurrentVersion
を使って取得します。
ただ、ClickOnceで配布・起動された時のみ値を取得でき、それ以外の場合は空白となります。
参考:ApplicationDeployment.CurrentVersion プロパティ (System.Deployment.Application)
ClickOnceでのファイルの配布
アプリで使う画像ファイル
WPFの場合、リソースファイルは使わずにXAMLで対象の画像ファイルを指定します。
また、ファイルのプロパティにて、ビルドアクションにコンテンツ
を設定しておきます。
参考:XAMLにてImageコントロール内に画像を表示する - プログラミング備忘録
テキストファイルをデータファイルとして配布する
プロジェクトのPropertiesへの設定として以下を行います。
なお、データファイルとして配布する場合、アプリをアンインストールするとファイルが削除されてしまうことに注意します。
- すべてのファイルを表示して、対象のテキストファイルをプロジェクトに含める
- ビルドアクションを
コンテンツ
にする - 発行タブのアプリケーションボタンで、該当のファイルの発行の状況を
データファイル
にする
また、データファイルのディレクトリは以下の方法で取得できます。
System.Deployment.Application.ApplicationDeployment.CurrentDeployment.DataDirectory.ToString()
参考:
テキストファイルをClickOnceのキャッシュ領域へ配布する
キャッシュ領域の場合はアンインストールしてもファイルは残る一方で、ClickOnce発行ごとにファイルが配信されます。
- すべてのファイルを表示して、対象のテキストファイルをプロジェクトに含める
- ビルドアクションを
コンテンツ
にする - 出力ディレクトリにコピーを
常にコピーする
にする
また、キャッシュ領域のディレクトリは以下の方法で取得できます。
System.AppDomain.CurrentDomain.BaseDirectory
参考:
- c# - Getting the application's directory from a WPF application - Stack Overflow
- アプリケーションの実行パスを取得する。どの方法が適切か検討してみた。 - tekkの日記 C#,VB.NET
コード署名の追加
コード署名を追加しないでClickOnceで配布した際、プログラムのインストールや更新時の発行者欄に「不明な発行元です」というメッセージが表示されます。
そのため、Active Directory環境下でAD CSが構築済の場合、コード証明書を発行し署名を追加します。
コード証明書については、AD CS にてコード証明書を発行し、MMCの証明書でユーザーアカウントの個人に発行した証明書を追加します。
参考:AD CS でコード証明書を発行する - スクリプトセンター
なお、既存の証明書テンプレートコード証明書
(有効期間1年)を使って発行しても良いのですが、複製して期間を延長したものを使用しても特に問題はありませんでした。
証明書を追加後、プロジェクトのプロパティ「署名」にて、以下の設定を行います(なお、今回はアセンブリへの署名は行いません)。
設定後にClickOnceでアプリを配信すると、発行者欄に証明書が表示されるようになります。
プロジェクトのPropertiesの発行タブの設定
発行タブの設定により、ClickOnceを発行する共有フォルダの場所や、プログラム起動前の更新チェックなどを指定できます。
参考:連載 ClickOnceの真実:第3回 Visual Studio 2005でClickOnceを極めよう (2/2) - @IT
今回は、ClickOnceアプリを共有フォルダで配信する、クローズな社内LANで利用することを想定して設定してみました。
タブ | 種類 | 項目 | 内容 |
---|---|---|---|
発行 | 発行場所 | 発行フォルダーの場所 | <ファイルサーバー名>\共有フォルダ\ |
〃 | インストールモードと設定 | アプリケーションはオフラインでも利用できる | ●チェックする |
〃 | 更新ボタン | アプリケーションの更新を確認する | ■チェックする |
〃 | 〃 | アプリケーションの更新を確認する方法 | ●アプリケーションの開始前に行う |
〃 | オプション - 説明 | 発行者名 | <任意の名前> |
〃 | オプション - 説明 | スイート名 | <任意の名前> |
〃 | オプション - 説明 | 製品名 | <任意の名前> |
〃 | オプション - マニフェスト | URLからアプリケーションが起動されるのを禁止する | ■チェックする |
〃 | オプション - マニフェスト | デスクトップショートカットの作成 | ■チェックする |
なお、発行者名・スイート名・製品名を入力すると、すべてのプログラムの中に
発行者名(フォルダ) `-- スイート名(フォルダ) `-- 製品名(ショートカットアイコン)
の形でフォルダとショートカットアイコンが作成されます。
ClickOnceでの更新の強制
上記のプロジェクトのPropertiesの発行タブの設定により、アプリの更新をほぼ強制することができますが、
- ユーザーがスキップを選んでも、プログラムの更新を強制する
- スタートメニューから起動可能にする
- 「このアプリケーションに最低限必要なバージョンを指定する」のは毎回更新するのが手間なのでやりたくない
ということもあるかもしれないので、コードでアップデートを強制するようにします(なお、System.Windows.Forms
の参照設定が必要になります)。
if (System.Deployment.Application.ApplicationDeployment.IsNetworkDeployed) { var deploy = System.Deployment.Application.ApplicationDeployment.CurrentDeployment; if (deploy.CheckForUpdate()) { deploy.Update(); System.Windows.Forms.Application.Restart(); System.Windows.Application.Current.Shutdown(); } }
- c# - How do I restart a WPF application? - Stack Overflow
- How Not To Restart A ClickOnce Application | Brian Lachniet
Windows Formアプリの場合は以下が参考になります。
また、自社環境以外でClickOnceを使うには、以下も参考になるかもしれません。
開発者以外が配置する ClickOnce アプリケーションの作成
サンプルコード
CSharp-Sample/ClickOnceApp at master - thinkAmi/CSharp-Sample
なお、サンプルコードにはコード署名を付けていません。