逐步解說:為 ClickOnce 應用程式建立自訂安裝程式
任何以 .exe 檔案為基礎的 ClickOnce 應用程式都可以由自訂安裝程式以無訊息方式安裝及更新。 自訂安裝程式可以在安裝期間實作自訂使用者體驗,包括安全性和維護作業的自訂對話方塊。 若要執行安裝作業,自訂安裝程式會使用類別 InPlaceHostingManager。 本逐步解說示範如何建立自訂安裝程式,以無訊息方式安裝 ClickOnce 應用程式。
注意
.NET Core 和 .NET 5 和更新版本中不支援 System.Deployment.Application 命名空間中的 ApplicationDeployment 類別和 API。 .NET 7 支援存取應用程式部署屬性的新方法。 如需詳細資訊,請參閱在 .NET 中存取 ClickOnce 部署屬性。 .NET 7 不支援 ApplicationDeployment 方法的同等項。
必要條件
建立自訂 ClickOnce 應用程式安裝程式
在您的 ClickOnce 應用程式中,新增 System.Deployment 和 System.Windows.Forms 的參考。
將新類別新增至您的應用程式,並指定任何名稱。 這個逐步解說使用的名稱為
MyInstaller
。將下列
Imports
或using
指示詞新增至新類別的頂端。將下列方法加入類別。
這些方法會呼叫 InPlaceHostingManager 方法來下載部署資訊清單、判斷提示適當的權限、要求使用者安裝權限,然後將應用程式下載並安裝到 ClickOnce 快取中。 自訂安裝程式可以指定 ClickOnce 應用程式是預先信任的,也可以將信任決策延遲至 AssertApplicationRequirements 方法呼叫。 此程式碼會預先信任應用程式。
注意
預先信任指派的權限不能超過自訂安裝程式程式碼的權限。
InPlaceHostingManager iphm = null; public void InstallApplication(string deployManifestUriStr) { try { Uri deploymentUri = new Uri(deployManifestUriStr); iphm = new InPlaceHostingManager(deploymentUri, false); } catch (UriFormatException uriEx) { MessageBox.Show("Cannot install the application: " + "The deployment manifest URL supplied is not a valid URL. " + "Error: " + uriEx.Message); return; } catch (PlatformNotSupportedException platformEx) { MessageBox.Show("Cannot install the application: " + "This program requires Windows XP or higher. " + "Error: " + platformEx.Message); return; } catch (ArgumentException argumentEx) { MessageBox.Show("Cannot install the application: " + "The deployment manifest URL supplied is not a valid URL. " + "Error: " + argumentEx.Message); return; } iphm.GetManifestCompleted += new EventHandler<GetManifestCompletedEventArgs>(iphm_GetManifestCompleted); iphm.GetManifestAsync(); } void iphm_GetManifestCompleted(object sender, GetManifestCompletedEventArgs e) { // Check for an error. if (e.Error != null) { // Cancel download and install. MessageBox.Show("Could not download manifest. Error: " + e.Error.Message); return; } // bool isFullTrust = CheckForFullTrust(e.ApplicationManifest); // Verify this application can be installed. try { // the true parameter allows InPlaceHostingManager // to grant the permissions requested in the applicaiton manifest. iphm.AssertApplicationRequirements(true) ; } catch (Exception ex) { MessageBox.Show("An error occurred while verifying the application. " + "Error: " + ex.Message); return; } // Use the information from GetManifestCompleted() to confirm // that the user wants to proceed. string appInfo = "Application Name: " + e.ProductName; appInfo += "\nVersion: " + e.Version; appInfo += "\nSupport/Help Requests: " + (e.SupportUri != null ? e.SupportUri.ToString() : "N/A"); appInfo += "\n\nConfirmed that this application can run with its requested permissions."; // if (isFullTrust) // appInfo += "\n\nThis application requires full trust in order to run."; appInfo += "\n\nProceed with installation?"; DialogResult dr = MessageBox.Show(appInfo, "Confirm Application Install", MessageBoxButtons.OKCancel, MessageBoxIcon.Question); if (dr != System.Windows.Forms.DialogResult.OK) { return; } // Download the deployment manifest. iphm.DownloadProgressChanged += new EventHandler<DownloadProgressChangedEventArgs>(iphm_DownloadProgressChanged); iphm.DownloadApplicationCompleted += new EventHandler<DownloadApplicationCompletedEventArgs>(iphm_DownloadApplicationCompleted); try { // Usually this shouldn't throw an exception unless AssertApplicationRequirements() failed, // or you did not call that method before calling this one. iphm.DownloadApplicationAsync(); } catch (Exception downloadEx) { MessageBox.Show("Cannot initiate download of application. Error: " + downloadEx.Message); return; } } /* private bool CheckForFullTrust(XmlReader appManifest) { if (appManifest == null) { throw (new ArgumentNullException("appManifest cannot be null.")); } XAttribute xaUnrestricted = XDocument.Load(appManifest) .Element("{urn:schemas-microsoft-com:asm.v1}assembly") .Element("{urn:schemas-microsoft-com:asm.v2}trustInfo") .Element("{urn:schemas-microsoft-com:asm.v2}security") .Element("{urn:schemas-microsoft-com:asm.v2}applicationRequestMinimum") .Element("{urn:schemas-microsoft-com:asm.v2}PermissionSet") .Attribute("Unrestricted"); // Attributes never have a namespace if (xaUnrestricted != null) if (xaUnrestricted.Value == "true") return true; return false; } */ void iphm_DownloadApplicationCompleted(object sender, DownloadApplicationCompletedEventArgs e) { // Check for an error. if (e.Error != null) { // Cancel download and install. MessageBox.Show("Could not download and install application. Error: " + e.Error.Message); return; } // Inform the user that their application is ready for use. MessageBox.Show("Application installed! You may now run it from the Start menu."); } void iphm_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e) { // you can show percentage of task completed using e.ProgressPercentage }
若要嘗試從程式碼安裝,請呼叫
InstallApplication
方法。 例如,如果您將類別MyInstaller
命名,您可能會以下列方式呼叫InstallApplication
。
下一步
ClickOnce 應用程式也可以新增自訂更新邏輯,包括自訂使用者介面,以在更新處理序期間顯示。 如需詳細資訊,請參閱UpdateCheckInfo。 ClickOnce 應用程式也可以使用 <customUX>
元素來抑制標準 [開始] 功能表項目、快捷方式和 [新增或移除程式] 項目。 如需詳細資訊,請參閱 <entryPoint> 元素 和 ShortcutAppId。