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

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

Note

NET Core および .NET 5 以降のバージョンでは、System.Deployment.Application 名前空間内の ApplicationDeployment クラスと API はサポートされていません。 .NET 7 では、アプリケーションの配置プロパティにアクセスするための新しいメソッドがサポートされています。 詳細については、.NET の ClickOnce 配置プロパティへのアクセスに関するページを参照してください。 .NET 7 では、ApplicationDeployment メソッドと同等のメソッドはサポートされていません。

Note

これを行うには、アプリケーションが完全な信頼で実行する必要があります。

前提条件

このチュートリアルを実行するには、次のいずれかのコンポーネントが必要になります。

  • Windows SDK。 Windows SDK は、Microsoft ダウンロード センターからダウンロードできます。

  • Visual Studio。

プロジェクトを作成する

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

  1. ClickOnceOnDemand という名前のディレクトリを作成します。

  2. Windows SDK コマンド プロンプトまたは Visual Studio コマンド プロンプトを開きます。

  3. ClickOnceOnDemand ディレクトリに変更します。

  4. 次のコマンドを使って、公開キーと秘密キーのペアを生成します。

    sn -k TestKey.snk
    
  5. メモ帳などのテキスト エディターを使って、Message という名前の単一プロパティを持つ、DynamicClass という名前のクラスを定義します。

    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!");
                }
            }
        }
    }
    
  6. 使用する言語に応じて、テキストを ClickOnceLibrary.cs または ClickOnceLibrary.vb というファイル名にし、ClickOnceOnDemand ディレクトリに保存します。

  7. ファイルをアセンブリにコンパイルします。

    csc /target:library /keyfile:TestKey.snk ClickOnceLibrary.cs
    
  8. アセンブリの公開キー トークンを取得するには、次のコマンドを使用します。

    sn -T ClickOnceLibrary.dll
    
  9. テキスト エディターを使って新しいファイルを作成し、次のコードを入力します。 このコードでは、必要に応じて ClickOnceLibrary アセンブリをダウンロードする Windows フォーム アプリケーションが作成されます。

    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);
            }
        }
    }
    
  10. コードで、LoadFile への呼び出しを探します。

  11. PublicKeyToken を、先ほど取得した値に設定します。

  12. ファイルを Form1.cs または Form1.vb として保存します。

  13. 次のコマンドを使って、実行可能ファイルにコンパイルします。

    csc /target:exe /reference:ClickOnceLibrary.dll Form1.cs
    

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

MageUI.exe を使ってアセンブリを ClickOnce アプリケーションでのオプションとしてマークするには

  1. MageUI.exe を使用し、「チュートリアル: ClickOnce アプリケーションを手動で配置する」の説明に従って、アプリケーション マニフェストを作成します。 アプリケーション マニフェストについては、次の設定を使用します。

    • アプリケーション マニフェストの名前は ClickOnceOnDemand にします。

    • [ファイル] ページの [ClickOnceLibrary.dll] 行で、[ファイルの種類] 列を [なし] に設定します。

    • [ファイル] ページの [ClickOnceLibrary.dll] 行で、[グループ] 列に「ClickOnceLibrary.dll」と入力します。

  2. MageUI.exe を使用し、「チュートリアル: ClickOnce アプリケーションを手動で配置する」の説明に従って、配置マニフェストを作成します。 配置マニフェストについては、次の設定を使用します。

    • 配置マニフェストの名前は ClickOnceOnDemand にします。

新しいアセンブリをテストする

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

  1. ClickOnce 配置を Web サーバーにアップロードします。

  2. 配置マニフェストの URL を入力して、ClickOnce を使って配置されたアプリケーションを Web ブラウザーから起動します。 ClickOnce アプリケーション ClickOnceOnDemand を呼び出し、adatum.com のルート ディレクトリにアップロードした場合、URL は次のようになります。

    http://www.adatum.com/ClickOnceOnDemand/ClickOnceOnDemand.application
    
  3. メイン フォームが表示されたら、 Buttonをクリックします。 メッセージ ボックス ウィンドウに "Hello, World!" という文字列が表示されます。