逐步解說:依需求使用設計工具以 ClickOnce 部署 API 下載組件
根據預設,在 ClickOnce 應用程式中包含的所有組件 (Assembly),都會在應用程式首次執行時下載。 不過,您可以將應用程式分成幾個部分,分別供一小群使用者使用。 在此情況下,只有在建立一種類型的組件時,才需要下載組件。 下列逐步解說會示範如何將應用程式中的某些組件標記為「選擇項」,以及如何在 Common Language Runtime 要求這些組件時,使用 System.Deployment.Application 命名空間中的類別來下載這些組件。
注意事項 |
---|
您的應用程式需要在完全信任的狀態下執行,才能使用這個程序。 |
注意事項 |
---|
根據您目前使用的設定或版本,您所看到的對話方塊與功能表指令可能會與 [說明] 中描述的不同。如果要變更設定,請按一下 [工具] 功能表上的 [匯入和匯出設定]。如需詳細資訊,請參閱 Visual Studio 中的自訂開發設定。 |
建立專案
以 Visual Studio 建立使用視需要下載之組件的專案
在 Visual Studio 中建立新的 Windows Form 專案。 在 [檔案] 功能表上指向 [加入],然後按一下 [新增專案]。 在對話方塊中選擇 [類別庫] 專案,並將它命名為 ClickOnceLibrary。
注意事項 在 Visual Basic 中,我們建議您修改專案屬性,將這個專案的根命名空間變更為 Microsoft.Samples.ClickOnceOnDemand,或是您所選擇的命名空間。為了容易說明,本逐步解說會讓這兩個專案位於相同的命名空間。
定義名為 DynamicClass,並具有名為 Message 單一屬性 (Property) 的類別。
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!"); } } } }
在 [方案總管] 中選取 Windows Form 專案。 加入 System.Deployment.Application 組件的參考,並加入 ClickOnceLibrary 專案的專案參考。
注意事項 在 Visual Basic 中,我們建議您修改專案屬性,將這個專案的根命名空間變更為 Microsoft.Samples.ClickOnceOnDemand,或是您所選擇的命名空間。為了容易說明,本逐步解說會讓這兩個專案位於相同的命名空間。
以滑鼠右鍵按一下表單,然後按一下功能表中的 [檢視程式碼],並將下列參考加入至表單。
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;
加入下列程式碼以視需要下載此組件。 這段程式碼會示範如何使用泛型 Dictionary 類別,將一組組件對應到群組名稱。 因為在這個逐步解說中,我們只會下載單一組件,因此群組中只會有一個組件。 在實際的應用中,您可能會想要同時下載所有與應用程式之單一功能相關的組件。 此對應表讓您能將屬於某項功能的所有 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); }
在 [檢視] 功能表上,按一下 [工具箱]。 將 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 應用程式中的組件標記為選擇項
以滑鼠右鍵按一下 [方案總管] 中的 Windows Form 專案,並按一下 [屬性]。 選取 [發行] 索引標籤。
按一下 [應用程式檔案] 按鈕。
尋找 ClickOnceLibrary.dll 的清單。 將 [發行狀態] 下拉式清單方塊設定為 [包含]。
展開 [群組] 下拉式方塊並選取 [新增]。 輸入 ClickOnceLibrary 這個名稱當做新的群組名稱。
依照 如何:使用發行精靈發行 ClickOnce 應用程式之中的描述,繼續發行您的應用程式。
使用資訊清單產生和編輯工具 - 圖形用戶端 (MageUI.exe),將 ClickOnce 應用程式中的組件標記為選擇項
依照逐步解說:手動部署 ClickOnce 應用程式中的說明,建立您的 ClickOnce 資訊清單。
在關閉 MageUI.exe 之前,選取包含您部署的應用程式資訊清單之索引標籤,並在該索引標籤內選取 [檔案] 索引標籤。
在應用程式檔案的清單中找到 ClickOnceLibrary.dll,並將其 [檔案類型] 欄設定為 [無]。 對 [群組] 欄輸入 ClickOnceLibrary.dll。
測試新組件
若要測試視需要下載的組件
啟動以 ClickOnce 部署的應用程式。
當您的主表單出現時,按下 Button。 您應該會看到在訊息方塊視窗中顯示 "Hello, World!" 的字串