更新 : 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 ディレクトリに移動します。
次のコマンドを使用して、公開キーと秘密キーのペアを生成します。
メモ帳などのテキスト エディタを使用して、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 アプリケーションを手動で配置する」の説明に従って配置マニフェストを作成します。配置マニフェストに、以下の設定を使用します。
オンデマンド アセンブリをテストするには
作成した ClickOnce 配置を Web サーバーにアップロードします。
配置マニフェストの URL を Web ブラウザに入力して、ClickOnce で配置したアプリケーションを Web ブラウザから起動します。ClickOnce アプリケーションの名前が ClickOnceOnDemand であり、そのアップロード先が adatum.com のルート ディレクトリの場合、入力する URL は次のようになります。
http://www.adatum.com/ClickOnceOnDemand/ClickOnceOnDemand.application
メイン フォームが表示されたら、Button をクリックします。"Hello, World!" と書かれたメッセージ ボックスが表示されます。
参照