Tutorial: Usar una acción personalizada para compilar un binario en código nativo durante la instalación

Puede definir acciones personalizadas a fin de especificar comandos que se ejecutan después de una instalación. Por ejemplo, en este tutorial, definiremos una acción personalizada y pasaremos el nombre de ruta de acceso de un archivo EXE a la propiedad CustomActionData, a fin de compilar el archivo ejecutable a código nativo una vez instalada la aplicación.

Nota

Es posible que su equipo muestre nombres o ubicaciones diferentes para algunos de los elementos de la interfaz de usuario de Visual Studio incluidos en las instrucciones siguientes. La edición de Visual Studio que se tenga y la configuración que se utilice determinan estos elementos. Para obtener más información, vea Valores de configuración de Visual Studio.

Para crear una aplicación de explorador web que se va a implementar

  1. En el menú Archivo, elija Nuevo y haga clic en Proyecto.

  2. Haga clic en Aplicación de Windows Forms.

  3. En el Nombre, escriba BrowserSample y, a continuación, haga clic en Aceptar.

  4. En el menú Ver, haga clic en Cuadro de herramientas.

  5. Expanda Todos los formularios de Windows Forms y arrastre un control Panel hasta la parte superior izquierda del formulario.

  6. En el Diseñador de Windows Forms, arrastre un control TextBox y un control Button al control Panel.

  7. En el Diseñador de Windows Forms, arrastre un control WebBrowser y sitúelo debajo del Panel.

  8. Expanda el tamaño del formulario para que se ajuste a todos los controles.

  9. En el Diseñador de Windows Forms, haga doble clic en el control Panel.

  10. En la Ventana Propiedades, cambie la propiedad Dock que aparece en Diseño a Top.

  11. En el Diseñador de Windows Forms, haga doble clic en el control WebBrowser.

  12. En la ventana Propiedades, cambie la propiedad Dock que aparece en Diseño a Fill.

  13. En el Diseñador de Windows Forms, haga clic en el control Button.

  14. En la Ventana Propiedades, cambie la propiedad Text bajo Apariencia a Ir.

  15. Cambie el tamaño de los elementos Form, Panel, Textbox, Button y WebBrowser según sus preferencias.

  16. En el Diseñador de Windows Forms, haga doble clic en el botón Ir.

    Aparecerá la vista de código del archivo de código Form1.

  17. Agregue el siguiente código, que agrega la funcionalidad de exploración web a la aplicación. El texto del control TextBox es la barra de direcciones del control WebBrowser. La acción tiene lugar al hacer clic en el botón Ir.

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        WebBrowser1.Navigate(TextBox1.Text)
    End Sub
    
    private void button1_Click(object sender, EventArgs e)
    {
        webBrowser1.Navigate(textBox1.Text);
    }
    
  18. Para probar el explorador, presione F5.

    Se abrirá el formulario.

  19. En el cuadro de texto, escriba https://www.microsoft.com. A continuación, haga clic en Ir.

    Se abre el sitio web de Microsoft.

Para crear la clase de acción personalizada

  1. En el menú Archivo, elija Agregar y, después, haga clic en Nuevo proyecto.

  2. En el cuadro de diálogo Agregar nuevo proyecto, haga clic en Windows y en Biblioteca de clases.

  3. En el cuadro Nombre, escriba NGenCustomAction y, a continuación, haga clic en Aceptar.

  4. En el menú Proyecto, haga clic en Agregar nuevo elemento.

  5. En el cuadro de diálogo Agregar nuevo elemento, haga clic en General y, a continuación, en Clase del instalador. En el cuadro Nombre, escriba NGenCustomAction y, a continuación, haga clic en Agregar.

    Nota

    Asegúrese de agregar una Clase del instalador; de lo contrario, el archivo de código no tendrá las instrucciones using necesarias.

  6. En el Explorador de soluciones, elimine el archivo de código Class1 del proyecto NGenCustomAction.

Para agregar código a la acción personalizada

  1. En el Explorador de soluciones (o en la superficie de diseño), haga clic con el botón secundario del mouse en el archivo de código NGenCustomAction. A continuación, haga clic en Ver código para abrir el Editor de código. Agregue el código siguiente al principio del módulo.

    Imports System.IO
    Imports System.Diagnostics
    
    using System.IO;
    using System.Diagnostics;
    
  2. Actualice la declaración de clase de modo que herede de la clase System.Configuration.Install.Installer.

    Inherits System.Configuration.Install.Installer
    
    : System.Configuration.Install.Installer
    
  3. En el archivo de código NGenCustomAction, agregue el siguiente método auxiliar para generar el archivo de código de imagen nativa de cualquier ensamblado.

        <System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand)> _
    Private Sub ngenCA(ByVal savedState As System.Collections.IDictionary, ByVal ngenCommand As String)
            Dim argsArray As [String]()
    
            If String.Compare(ngenCommand, "install", StringComparison.OrdinalIgnoreCase) = 0 Then
                Dim args As [String] = Context.Parameters("Args")
                If [String].IsNullOrEmpty(args) Then
                    Throw New InstallException("No arguments specified")
                End If
    
                Dim separators As Char() = {";"c}
                argsArray = args.Split(separators)
                'It is Ok to 'ngen uninstall' assemblies which were not installed
                savedState.Add("NgenCAArgs", argsArray)
            Else
                argsArray = DirectCast(savedState("NgenCAArgs"), [String]())
            End If
    
            ' Gets the path to the Framework directory.
            Dim fxPath As String = System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory()
    
            For i As Integer = 0 To argsArray.Length - 1
                Dim arg As String = argsArray(i)
                ' Quotes the argument, in case it has a space in it.
                arg = """" & arg & """"
    
                Dim command As String = (ngenCommand & " ") + arg
    
                Dim si As New ProcessStartInfo(Path.Combine(fxPath, "ngen.exe"), command)
                si.WindowStyle = ProcessWindowStyle.Hidden
    
                Dim p As Process
    
                Try
                    Context.LogMessage((">>>>" & Path.Combine(fxPath, "ngen.exe ")) + command)
                    p = Process.Start(si)
                    p.WaitForExit()
                Catch ex As Exception
                    Throw New InstallException("Failed to ngen " & arg, ex)
                End Try
            Next
        End Sub
    
            [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand)]
            private void ngenCA(System.Collections.IDictionary savedState, string ngenCommand)
            {
                String[] argsArray;
    
                if (string.Compare(ngenCommand, "install", StringComparison.OrdinalIgnoreCase) == 0)
                {
                    String args = Context.Parameters["Args"];
                    if (String.IsNullOrEmpty(args))
                    {
                        throw new InstallException("No arguments specified");
                    }
    
                    char[] separators = { ';' };
                    argsArray = args.Split(separators);
                    savedState.Add("NgenCAArgs", argsArray); //It is Ok to 'ngen uninstall' assemblies which were not installed
                }
                else
                {
                    argsArray = (String[])savedState["NgenCAArgs"];
                }
    
                // Gets the path to the Framework directory.
                string fxPath = System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory();
    
                for (int i = 0; i < argsArray.Length; ++i)
                {
                    string arg = argsArray[i];
                    // Quotes the argument, in case it has a space in it.
                    arg = "\"" + arg + "\"";
    
                    string command = ngenCommand + " " + arg;
    
                    ProcessStartInfo si = new ProcessStartInfo(Path.Combine(fxPath, "ngen.exe"), command);
                    si.WindowStyle = ProcessWindowStyle.Hidden;
    
                    Process p;
    
                    try
                    {
                        Context.LogMessage(">>>>" + Path.Combine(fxPath, "ngen.exe ") + command);
                        p = Process.Start(si);
                        p.WaitForExit();
                    }
                    catch (Exception ex)
                    {
                        throw new InstallException("Failed to ngen " + arg, ex);
                    }
                }
            }
    
    
  4. En el archivo de código NGenCustomAction, agregue el siguiente procedimiento para invalidar los procedimientos Install, Commit, Rollback y Uninstall de la clase base.

    <System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand)> _
    Public Overloads Overrides Sub Install(ByVal savedState As System.Collections.IDictionary)
        MyBase.Install(savedState)
        Context.LogMessage(">>>> ngenCA: install")
        ngenCA(savedState, "install")
    End Sub
    
    <System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand)> _
    Public Overrides Sub Commit(ByVal savedState As System.Collections.IDictionary)
        MyBase.Commit(savedState)
        Context.LogMessage(">>>> ngenCA: commit")
    End Sub
    
    <System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand)> _
    Public Overloads Overrides Sub Uninstall(ByVal savedState As System.Collections.IDictionary)
        MyBase.Uninstall(savedState)
        Context.LogMessage(">>>> ngenCA: uninstall")
        ngenCA(savedState, "uninstall")
    End Sub
    
    <System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand)> _
    Public Overloads Overrides Sub Rollback(ByVal savedState As System.Collections.IDictionary)
        MyBase.Rollback(savedState)
        Context.LogMessage(">>>> ngenCA: rollback")
        ngenCA(savedState, "uninstall")
    End Sub
    
    [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand)]
    public override void Install(System.Collections.IDictionary savedState)
    {
        base.Install(savedState);
        Context.LogMessage(">>>> ngenCA: install");
        ngenCA(savedState, "install");
    }
    
    [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand)]
    public override void Commit(IDictionary savedState)
    {
        base.Commit(savedState);
        Context.LogMessage(">>>> ngenCA: commit");
    }
    
    [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand)]
    public override void Uninstall(System.Collections.IDictionary savedState)
    {
        base.Uninstall(savedState);
        Context.LogMessage(">>>> ngenCA: uninstall");
        ngenCA(savedState, "uninstall");
    }
    
    [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand)]
    public override void Rollback(System.Collections.IDictionary savedState)
    {
        base.Rollback(savedState);
        Context.LogMessage(">>>> ngenCA: rollback");
        ngenCA(savedState, "uninstall");
    }
    

Para agregar un proyecto de implementación para la aplicación de ejemplo de explorador

  1. En el menú Archivo, elija Agregar y, después, haga clic en Nuevo proyecto.

  2. En el cuadro de diálogo Agregar nuevo proyecto, abra Otros tipos de proyectos, abra Proyectos de instalación e implementación, haga clic en Instalador de Visual Studio y, a continuación, en Proyecto de instalación.

  3. En el cuadro Nombre, escriba Instalador de ejemplo de explorador y, a continuación, haga clic en Aceptar.

  4. En el Editor del sistema de archivos, seleccione la Carpeta de la aplicación. En el menú Acción, haga clic en Agregar.

    Aparecerá el cuadro de diálogo Agregar grupo de resultados del proyecto.

  5. En el cuadro combinado desplegable Proyecto, seleccione BrowserSample, haga clic en Resultados del proyecto y, a continuación, haga clic en Aceptar.

  6. En el Editor del sistema de archivos, seleccione la Carpeta de la aplicación. En el menú Acción, haga clic en Agregar.

    Aparecerá el cuadro de diálogo Agregar grupo de resultados del proyecto.

  7. En el cuadro combinado desplegable Proyecto, seleccione NGenCustomAction, haga clic en Resultados del proyecto y, a continuación, haga clic en Aceptar.

Para agregar la acción personalizada NGEN al proyecto de instalación

  1. En el Explorador de soluciones, haga en el proyecto Instalador de ejemplo de explorador.

  2. En el menú Ver, elija Editor y, a continuación, haga clic en Acciones personalizadas.

  3. En el Editor de acciones personalizadas, seleccione el nodo Acciones personalizadas.

  4. En el menú Acción, haga clic en Agregar acción personalizada.

  5. En el cuadro de diálogo Seleccionar elemento en el proyecto, haga doble clic en la Carpeta de la aplicación y, a continuación, seleccione Resultado principal desde NGenCustomAction (activa) y haga clic en Aceptar.

    Se agrega la acción personalizada NGen a los cuatro nodos de acción personalizada.

  6. En el nodo Instalar, haga clic en Resultado principal desde NGenCustomAction (activa).

  7. En la ventana Propiedades, cambie la propiedad CustomActionData a /Args="[TARGETDIR]BrowserSample.exe". Incluya las comillas.

    Nota

    La propiedad [TARGETDIR] es la ubicación del archivo ejecutable instalado. La acción personalizada utiliza ngen.exe para convertir el archivo ejecutable instalado en una imagen nativa.

  8. En el Explorador de soluciones, haga en el proyecto de instalación Instalador de ejemplo de explorador.

  9. En el menú Compilar, haga clic en Compilar Instalador de ejemplo de explorador.

Para comprobar la generación de código nativo

  1. Navegue a la carpeta de instalación y busque el archivo BrowserSample.exe. Por ejemplo %Archivos de programa%\CompanyName\Instalador de ejemplo de explorador\BrowserSample.exe.

  2. En el símbolo del sistema de Visual Studio, compruebe que el archivo ejecutable se precompiló a código nativo ejecutando el siguiente código:

    ngen.exe display FullPathToExe
    

    Por ejemplo, puede ejecutar el siguiente comando:

    ngen.exe display "C:\Program Files (x86)\Microsoft\Browser Sample Installer\BrowserSample.exe"
    

    Se muestra la siguiente salida del comando.

    Microsoft (R) CLR Native Image Generator - Version 4.0.21102.0
    Copyright (c) Microsoft Corporation.  All rights reserved.
    
    NGEN Roots:
    
    C:\Program Files (x86)\Microsoft\Browser Sample Installer\BrowserSample.exe
    
    NGEN Roots that depend on "c:\Program Files (x86)\Microsoft\Browser Sample Installer\BrowserSample.exe":
    
    C:\Program Files (x86)\Microsoft\Browser Sample Installer\BrowserSample.exe
    
    Native Images:
    
    BrowserSample, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null <debug>
    

    Nota

    Si ngen.exe no muestra una imagen nativa, puede encontrar los registros de ngen en uno de los siguientes directorios:

    %SystemRoot%\Microsoft.NET\Framework\v<versión de CLR> %SystemRoot%\Microsoft.NET\Framework64\v<versión de CLR>

    El archivo ngen.log es el más reciente para la solución de problemas.

Vea también

Referencia

CustomActionData (Propiedad)

Ngen.exe (Generador de imágenes nativas)

Conceptos

Proceso de ejecución administrada

Otros recursos

Administración de acciones personalizadas en la implementación