Share via


チュートリアル : デザイナーを使用し、ClickOnce 配置 API で必要に応じてアセンブリをダウンロードする

既定では、ClickOnce アプリケーションの最初の実行時に、そのアプリケーションに含まれるすべてのアセンブリがダウンロードされます。 しかしアプリケーションには、一部のユーザーだけが使用する機能が含まれている場合があります。 この場合は、そのような機能を使用するときにだけ、対応するアセンブリがダウンロードされるようにすることができます。 以下のチュートリアルでは、アプリケーション内の特定のアセンブリに "オプション" マークを付ける方法、および、共通言語ランタイム (CLR: Common Language Runtime) によって要求されたときに、System.Deployment.Application 名前空間にあるクラスを使用して、それらのアセンブリをダウンロードする方法を説明します。

注意

この手順を使用するには、アプリケーションが完全信頼で実行される必要があります。

注意

実際に画面に表示されるダイアログ ボックスとメニュー コマンドは、アクティブな設定またはエディションによっては、ヘルプの説明と異なる場合があります。 設定を変更するには、[ツール] メニューの [設定のインポートとエクスポート] をクリックします。 詳細については、「設定の操作」を参照してください。

プロジェクトの作成

オンデマンド アセンブリを使用するプロジェクトを Visual Studio で作成するには

  1. Visual Studio で Windows フォーム プロジェクトを新規作成します。 [ファイル] メニューの [追加] をポイントし、[新しいプロジェクト] をクリックします。 ダイアログ ボックスの [クラス ライブラリ] プロジェクトをクリックし、ClickOnceLibrary という名前を付けます。

    注意

    Visual Basic では、プロジェクトのプロパティを変更して、このプロジェクトのルート名前空間を Microsoft.Samples.ClickOnceOnDemand または独自の名前空間に変更することをお勧めします。 このチュートリアルでは、簡単にするために、2 つのプロジェクトを同じ名前空間に置いています。

  2. 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!");
                }
            }
        }
    }
    
  3. ソリューション エクスプローラーで、この Windows フォーム プロジェクトを選択します。 System.Deployment.Application アセンブリへの参照と、ClickOnceLibrary プロジェクトへのプロジェクト参照を追加します。

    注意

    Visual Basic では、プロジェクトのプロパティを変更して、このプロジェクトのルート名前空間を Microsoft.Samples.ClickOnceOnDemand または独自の名前空間に変更することをお勧めします。 このチュートリアルでは、簡単にするために、2 つのプロジェクトを同じ名前空間に置いています。

  4. フォームを右クリックします。ショートカット メニューの [コードの表示] をクリックし、次の参照をフォームに追加します。

    Imports System.Reflection
    Imports System.Deployment.Application
    Imports System.Collections.Generic
    Imports Microsoft.Samples.ClickOnceOnDemand
    Imports System.Security.Permissions
    
    using System.Reflection;
    using System.Deployment.Application;
    using Microsoft.Samples.ClickOnceOnDemand;
    using System.Security.Permissions;
    
  5. このアセンブリをオンデマンドでダウンロードするように、次のコードを追加します。 このコードは、一連のアセンブリを、Dictionary ジェネリック クラスを使ってグループ名にマップする方法を示しています。 このチュートリアルでダウンロードされるアセンブリは 1 つだけなので、グループに存在するアセンブリも 1 つしかありません。 実際のアプリケーションでは、アプリケーションの特定の機能に関連したすべてのアセンブリを同時にダウンロードするのが一般的です。 この処理は、特定の機能に属するすべての DLL とダウンロード グループ名をマッピング テーブルで関連付けることにより、簡単に行うことができます。

    ' 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 DllMappingTable As New Dictionary(Of String, String)()
    
    <SecurityPermission(SecurityAction.Demand, ControlAppDomain:=True)> _
    Sub New()
        ' This call is required by the Windows Form Designer.
        InitializeComponent()
    
        ' Add any initialization after the InitializeComponent() call.
        DllMappingTable("ClickOnceLibrary") = "ClickOnceLibrary"
    End Sub
    
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        AddHandler AppDomain.CurrentDomain.AssemblyResolve, AddressOf Me.CurrentDomain_AssemblyResolve
    End Sub
    
    Private Function CurrentDomain_AssemblyResolve(ByVal sender As Object, ByVal args As ResolveEventArgs) As System.Reflection.Assembly
        Dim NewAssembly As Assembly = Nothing
    
        If (ApplicationDeployment.IsNetworkDeployed) Then
            Dim Deploy As ApplicationDeployment = ApplicationDeployment.CurrentDeployment
    
            ' Get the DLL name from the argument.
            Dim NameParts As String() = args.Name.Split(",")
            Dim DllName As String = NameParts(0)
            Dim DownloadGroupName As String = DllMappingTable(DllName)
    
            Try
                Deploy.DownloadFileGroup(DownloadGroupName)
            Catch ex As Exception
                MessageBox.Show("Could not download file group from Web server. Contact administrator. Group name: " & DownloadGroupName & "; DLL name: " & args.Name)
                Throw (ex)
            End Try
    
            ' 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")
            Catch ex As Exception
                Throw (ex)
            End Try
        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.")
        End If
    
        Return NewAssembly
    End Function
    
    // 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>();
    
    [SecurityPermission(SecurityAction.Demand, ControlAppDomain=true)]
    public Form1()
    {
        InitializeComponent();
    
        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");
            }
            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);
    }
    
  6. [表示] メニューの [ツールボックス] をクリックします。 [ツールボックス] から Button をフォームにドラッグします。 このボタンをダブルクリックし、Click イベント ハンドラーに次のコードを追加します。

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim DC As New DynamicClass()
        MessageBox.Show("Message is " & DC.Message)
    End Sub
    
    private void getAssemblyButton_Click(object sender, EventArgs e)
    {
        DynamicClass dc = new DynamicClass();
        MessageBox.Show("Message: " + dc.Message);
    }
    

アセンブリをオプションとしてマークするには

Visual Studio を使用して ClickOnce アプリケーション内のアセンブリをオプションとしてマークするには

  1. ソリューション エクスプローラーで Windows フォーム プロジェクトを右クリックし、[プロパティ] をクリックします。 [発行] タブをクリックします。

  2. [アプリケーション ファイル] ボタンをクリックします。

  3. 一覧から ClickOnceLibrary.dll を探し、 [発行の状況] ボックスを [追加] に設定します。

  4. [ダウンロードグループ] ボックスの一覧の [新規作成] をクリックします。 新しいグループ名として「ClickOnceLibrary」を入力します。

  5. アプリケーションを公開します (「方法: 発行ウィザードを使用して ClickOnce アプリケーションを発行する」を参照)。

マニフェストの生成および編集用のグラフィカル ツール (MageUI.exe) で ClickOnce アプリケーションのアセンブリをオプションとしてマークするには

  1. ClickOnce マニフェストを作成します (「チュートリアル : ClickOnce アプリケーションを手動で配置する」を参照)。

  2. MageUI.exe を終了する前に、作成した配置のアプリケーション マニフェストが含まれているタブをクリックし、このページにある [Files] タブをクリックします。

  3. アプリケーション ファイルの一覧から ClickOnceLibrary.dll を探し、その [File Type] 列を [None] に設定します。 [Group] 列には、「ClickOnceLibrary.dll」と入力します。

新しいアセンブリのテスト

オンデマンド アセンブリをテストするには

  1. アプリケーションを ClickOnce で配置してから起動します。

  2. メイン フォームが表示されたら、Button をクリックします。 "Hello, World!" と書かれたメッセージ ボックスが表示されます。

参照

参照

ApplicationDeployment