チュートリアル : ClickOnce 配置 API を使用して必要に応じてアセンブリをダウンロードする
更新 : 2007 年 11 月
既定では、ClickOnce アプリケーションの最初の実行時に、そのアプリケーションに含まれるすべてのアセンブリがダウンロードされます。一方、アプリケーションには、一部のユーザーだけが使用する機能が含まれている場合があります。この場合は、そのような機能を使用するときにだけ、対応するアセンブリがダウンロードされるようにすることができます。以下のチュートリアルでは、アプリケーション内の特定のアセンブリを "オプション" としてマークを付ける方法、および、共通言語ランタイム (CLR: Common Language Runtime) によって要求されたときに、System.Deployment.Application 名前空間にあるクラスを使用して、それらのアセンブリをダウンロードする方法を説明します。
メモ : |
---|
この手順を使用するには、アプリケーションが完全信頼で実行される必要があります。 |
前提条件
このチュートリアルを実行するには、次のいずれかのコンポーネントが必要です。
.NET Framework 2.0 SDK。.NET Framework 2.0 SDK は、Visual Studio 2005 セットアップのコンポーネントとして利用できます。Microsoft ダウンロード センターからダウンロードすることもできます。
Windows SDK for Windows Vista。Windows SDK for Windows Vista は、Microsoft ダウンロード センターからダウンロードできます。
Microsoft Visual Studio 2005 以降。
プロジェクトの作成
オンデマンド アセンブリを使用するプロジェクトを作成するには
ClickOnceOnDemand という名前のディレクトリを作成します。
.NET Framework SDK コマンド プロンプトまたは Visual Studio コマンド プロンプトを開きます。
ClickOnceOnDemand ディレクトリに移動します。
次のコマンドを使用して、公開キーと秘密キーのペアを生成します。
sn -k TestKey.snk
メモ帳などのテキスト エディタを使用して、Message という名前のプロパティ 1 つを持つ DynamicClass クラスを定義します。
Public Class DynamicClass Sub New() End Sub Public ReadOnly Property Message() As String Get Message = "Hello, world!" End Get End Property End Class
using System; using System.Collections.Generic; using System.Text; namespace Microsoft.Samples.ClickOnceOnDemand { public class DynamicClass { public DynamicClass() {} public string Message { get { return ("Hello, world!"); } } } }
このテキストを、使用しているプログラミング言語に応じて ClickOnceLibrary.cs または ClickOnceLibrary.vb というファイル名で、ClickOnceOnDemand ディレクトリに保存します。
ファイルをアセンブリにコンパイルします。
csc /target:library /keyfile:TestKey.snk ClickOnceLibrary.cs
vbc /target:library /keyfile:TestKey.snk ClickOnceLibrary.vb
アセンブリの公開キー トークンを取得するには、次のコマンドを使用します。
sn -T ClickOnceLibrary.dll
テキスト エディタを使用して新しいファイルを作成し、次のコードを入力します。このコードは、必要なときに ClickOnceLibrary アセンブリをダウンロードする Windows フォーム アプリケーションを作成します。
Imports System Imports System.Windows.Forms Imports System.Deployment.Application Imports System.Drawing Imports System.Reflection Imports System.Collections.Generic Imports Microsoft.Samples.ClickOnceOnDemand Namespace Microsoft.Samples.ClickOnceOnDemand <System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, Unrestricted:=true)> _ Class Form1 Inherits Form ' Maintain a dictionary mapping DLL names to download file groups. This is trivial for this sample, ' but will be important in real-world applications where a feature is spread across multiple DLLs, ' and you want to download all DLLs for that feature in one shot. Dim DllMapping as Dictionary(Of String, String) = new Dictionary(of String, String)() Public Sub New() ' Add button to form. Dim GetAssemblyButton As New Button() GetAssemblyButton.Location = New Point(100, 100) GetAssemblyButton.Text = "Get assembly on demand" AddHandler GetAssemblyButton.Click, AddressOf GetAssemblyButton_Click Me.Controls.Add(GetAssemblyButton) DllMapping("ClickOnceLibrary") = "ClickOnceLibrary" AddHandler AppDomain.CurrentDomain.AssemblyResolve, AddressOf CurrentDomain_AssemblyResolve End Sub <STAThread()> _ Shared Sub Main() Application.EnableVisualStyles() Application.Run(New Form1()) End Sub Private Function CurrentDomain_AssemblyResolve(ByVal sender As Object, ByVal args As ResolveEventArgs) As Assembly If ApplicationDeployment.IsNetworkDeployed Then Dim deploy As ApplicationDeployment = ApplicationDeployment.CurrentDeployment ' Get the DLL name from the Name argument. Dim nameParts() as String = args.Name.Split(",") Dim dllName as String = nameParts(0) Dim downloadGroupName as String = DllMapping(dllName) Try deploy.DownloadFileGroup(downloadGroupName) Catch de As DeploymentException End Try ' Load the assembly. Dim newAssembly As Assembly = Nothing Try newAssembly = Assembly.LoadFile(Application.StartupPath & "\\" & dllName & ".dll," & _ "Version=1.0.0.0, Culture=en, PublicKeyToken=03689116d3a4ae33") Catch ex As Exception MessageBox.Show("Could not download assembly on demand.") End Try CurrentDomain_AssemblyResolve = newAssembly Else CurrentDomain_AssemblyResolve = Nothing End If End Function Private Sub GetAssemblyButton_Click(ByVal sender As Object, ByVal e As EventArgs) Dim ourClass As New DynamicClass() MessageBox.Show("DynamicClass string is: " + ourClass.Message) End Sub End Class End Namespace
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Reflection; using System.Deployment.Application; using Microsoft.Samples.ClickOnceOnDemand; namespace ClickOnceOnDemand { [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, Unrestricted=true)] public class Form1 : Form { // Maintain a dictionary mapping DLL names to download file groups. This is trivial for this sample, // but will be important in real-world applications where a feature is spread across multiple DLLs, // and you want to download all DLLs for that feature in one shot. Dictionary<String, String> DllMapping = new Dictionary<String, String>(); public static void Main() { Form1 NewForm = new Form1(); Application.Run(NewForm); } public Form1() { // Configure form. this.Size = new Size(500, 200); Button getAssemblyButton = new Button(); getAssemblyButton.Size = new Size(130, getAssemblyButton.Size.Height); getAssemblyButton.Text = "Test Assembly"; getAssemblyButton.Location = new Point(50, 50); this.Controls.Add(getAssemblyButton); getAssemblyButton.Click += new EventHandler(getAssemblyButton_Click); DllMapping["ClickOnceLibrary"] = "ClickOnceLibrary"; AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve); } /* * Use ClickOnce APIs to download the assembly on demand. */ private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) { Assembly newAssembly = null; if (ApplicationDeployment.IsNetworkDeployed) { ApplicationDeployment deploy = ApplicationDeployment.CurrentDeployment; // Get the DLL name from the Name argument. string[] nameParts = args.Name.Split(','); string dllName = nameParts[0]; string downloadGroupName = DllMapping[dllName]; try { deploy.DownloadFileGroup(downloadGroupName); } catch (DeploymentException de) { MessageBox.Show("Downloading file group failed. Group name: " + downloadGroupName + "; DLL name: " + args.Name); throw (de); } // Load the assembly. // Assembly.Load() doesn't work here, as the previous failure to load the assembly // is cached by the CLR. LoadFrom() is not recommended. Use LoadFile() instead. try { newAssembly = Assembly.LoadFile(Application.StartupPath + @"\" + dllName + ".dll," + "Version=1.0.0.0, Culture=en, PublicKeyToken=03689116d3a4ae33"); } catch (Exception e) { throw (e); } } else { //Major error - not running under ClickOnce, but missing assembly. Don't know how to recover. throw (new Exception("Cannot load assemblies dynamically - application is not deployed using ClickOnce.")); } return (newAssembly); } private void getAssemblyButton_Click(object sender, EventArgs e) { DynamicClass dc = new DynamicClass(); MessageBox.Show("Message: " + dc.Message); } } }
コード内で LoadFile の呼び出しを見つけます。
PublicKeyToken を、先に取得しておいた値に設定します。
ファイルに Form1.cs または Form1.vb の名前を付けて保存します。
これを、次のコマンドを使用して実行可能ファイルにコンパイルします。
csc /target:exe /reference:ClickOnceLibrary.dll Form1.cs
vbc /target:exe /reference:ClickOnceLibrary.dll Form1.vb
アセンブリをオプションとしてマークするには
MageUI.exe を使用して ClickOnce アプリケーション内のアセンブリをオプションとしてマークするには
MageUI.exe を使用して、「チュートリアル : ClickOnce アプリケーションを手動で配置する」の説明に従ってアプリケーション マニフェストを作成します。アプリケーション マニフェストに、次の設定を行います。
アプリケーション マニフェストに ClickOnceOnDemand という名前を付けます。
[Files] ページで、ClickOnceLibrary.dll 行の [File Type] 列を [None] に設定します。
[Files] ページで、ClickOnceLibrary.dll 行の [Group] 列に「ClickOnceLibrary.dll」と入力します。
MageUI.exe を使用して、「チュートリアル : ClickOnce アプリケーションを手動で配置する」の説明に従って配置マニフェストを作成します。配置マニフェストに、以下の設定を使用します。
- 配置マニフェストに ClickOnceOnDemand という名前を付けます。
新しいアセンブリのテスト
オンデマンド アセンブリをテストするには
作成した ClickOnce 配置を Web サーバーにアップロードします。
配置マニフェストの URL を Web ブラウザに入力して、ClickOnce で配置したアプリケーションを Web ブラウザから起動します。ClickOnce アプリケーションの名前が ClickOnceOnDemand であり、そのアップロード先が adatum.com のルート ディレクトリの場合、入力する URL は次のようになります。
http://www.adatum.com/ClickOnceOnDemand/ClickOnceOnDemand.application
メイン フォームが表示されたら、Button をクリックします。"Hello, World!" と書かれたメッセージ ボックスが表示されます。