Bagikan melalui


Panduan: Membuat alat penginstal kustom untuk aplikasi ClickOnce

Aplikasi ClickOnce apa pun berdasarkan file .exe dapat diinstal secara diam-diam dan diperbarui oleh alat penginstal kustom. Alat penginstal kustom dapat menerapkan pengalaman pengguna kustom selama penginstalan, termasuk kotak dialog kustom untuk operasi keamanan dan pemeliharaan. Untuk melakukan operasi penginstalan, alat penginstal kustom menggunakan kelas InPlaceHostingManager. Panduan ini menunjukkan cara membuat alat penginstal kustom yang secara diam-diam menginstal aplikasi ClickOnce.

Catatan

Kelas ApplicationDeployment dan API di System.Deployment.Application namespace tidak didukung dalam .NET Core dan .NET 5 dan versi yang lebih baru. Di .NET 7, metode baru untuk mengakses properti penyebaran aplikasi didukung. Untuk informasi selengkapnya, lihat Properti penyebaran Access ClickOnce di .NET. .NET 7 tidak mendukung metode ApplicationDeployment yang setara.

Prasyarat

Untuk membuat alat penginstal aplikasi ClickOnce kustom

  1. Di aplikasi ClickOnce Anda, tambahkan referensi ke System.Deployment dan System.Windows.Forms.

  2. Tambahkan kelas baru ke aplikasi Anda dan tentukan nama apa pun. Panduan ini menggunakan nama MyInstaller.

  3. Tambahkan Imports atau using arahan berikut di bagian atas kelas baru Anda.

    using System.Deployment.Application;
    using System.Windows.Forms;
    
  4. Tambahkan metode berikut ke kelas Anda.

    Metode ini memanggil metode InPlaceHostingManager untuk mengunduh manifes penyebaran, menegaskan izin yang sesuai, meminta izin kepada pengguna untuk menginstal, lalu mengunduh dan menginstal aplikasi ke dalam cache ClickOnce. Alat penginstal kustom dapat menentukan bahwa aplikasi ClickOnce telah dipercaya sebelumnya, atau dapat menunda keputusan kepercayaan ke panggilan metode AssertApplicationRequirements. Kode ini telah memercayai aplikasi sebelumnya.

    Catatan

    Izin yang ditetapkan dengan kepercayaan sebelumnya tidak boleh melebihi izin kode alat penginstal kustom.

    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. Untuk mencoba penginstalan dari kode Anda, panggil metode InstallApplication. Misalnya, jika Anda menamai kelas MyInstaller Anda, Anda dapat memanggil InstallApplication dengan cara berikut.

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

Langkah berikutnya

Aplikasi ClickOnce juga dapat menambahkan logika pembaruan kustom, termasuk antarmuka pengguna kustom untuk ditampilkan selama proses pembaruan. Untuk informasi selengkapnya, lihat UpdateCheckInfo . Aplikasi ClickOnce juga dapat menekan entri menu Start standar, pintasan, dan Menambahkan atau Menghapus entri Program dengan menggunakan elemen <customUX>. Untuk informasi selengkapnya, lihat elemen <entryPoint> dan ShortcutAppId.