Przewodnik: tworzenie niestandardowego instalatora dla aplikacji ClickOnce

Dowolna aplikacja ClickOnce oparta na pliku .exe może być instalowana w trybie dyskretnym i aktualizowana przez instalatora niestandardowego. Instalator niestandardowy może implementować niestandardowe środowisko użytkownika podczas instalacji, w tym niestandardowe okna dialogowe na potrzeby operacji zabezpieczeń i konserwacji. Aby wykonać operacje instalacji, instalator niestandardowy używa InPlaceHostingManager klasy . W tym przewodniku pokazano, jak utworzyć niestandardowy instalator, który dyskretnie instaluje aplikację ClickOnce.

Uwaga

Klasy ApplicationDeployment i interfejsy API w System.Deployment.Application przestrzeni nazw nie są obsługiwane w wersjach .NET Core i .NET 5 i nowszych. W programie .NET 7 jest obsługiwana nowa metoda uzyskiwania dostępu do właściwości wdrażania aplikacji. Aby uzyskać więcej informacji, zobacz Access ClickOnce deployment properties in .NET (Uzyskiwanie dostępu do właściwości wdrożenia ClickOnce na platformie .NET). Platforma .NET 7 nie obsługuje odpowiedników metod ApplicationDeployment.

Wymagania wstępne

Aby utworzyć niestandardowy instalator aplikacji ClickOnce

  1. W aplikacji ClickOnce dodaj odwołania do elementu System.Deployment i System.Windows.Forms.

  2. Dodaj nową klasę do aplikacji i określ dowolną nazwę. W tym przewodniku użyto nazwy MyInstaller.

  3. Dodaj następujące Imports dyrektywy lub using na początku nowej klasy.

    using System.Deployment.Application;
    using System.Windows.Forms;
    
  4. Dodaj następujące metody do klasy.

    Te metody wywołają InPlaceHostingManager metody pobierania manifestu wdrożenia, potwierdzenia odpowiednich uprawnień, poproś użytkownika o pozwolenie na instalację, a następnie pobierz i zainstaluj aplikację w pamięci podręcznej ClickOnce. Instalator niestandardowy może określić, że aplikacja ClickOnce jest wstępnie zaufana lub może odroczyć decyzję zaufania o wywołaniu AssertApplicationRequirements metody. Ten kod wstępnie ufa aplikacji.

    Uwaga

    Uprawnienia przypisane przez wstępne zaufanie nie mogą przekraczać uprawnień kodu instalatora niestandardowego.

    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
    }
    
  5. Aby spróbować zainstalować kod, wywołaj metodę InstallApplication . Jeśli na przykład nazwano klasę MyInstaller, możesz wywołać InstallApplication metodę w następujący sposób.

    MyInstaller installer = new MyInstaller();
    installer.InstallApplication(@"\\myServer\myShare\myApp.application");
    MessageBox.Show("Installer object created.");
    

Następne kroki

Aplikacja ClickOnce może również dodać niestandardową logikę aktualizacji, w tym niestandardowy interfejs użytkownika do wyświetlania podczas procesu aktualizacji. Aby uzyskać więcej informacji, zobacz UpdateCheckInfo. Aplikacja ClickOnce może również pominąć standardowy wpis menu Start, skrót i pozycję Dodaj lub Usuń programy przy użyciu <customUX> elementu . Aby uzyskać więcej informacji, zobacz <entryPoint> , element i ShortcutAppId.