Share via


逐步解說:使用自訂動作在安裝時將二進位編譯為機器碼

您可以定義自訂動作,指定要在安裝後執行的命令。 例如,在這個逐步解說中,定義自訂動作並將 EXE 的路徑名稱傳遞至 CustomActionData 屬性,以在安裝應用程式之後將可執行檔編譯為機器碼。

注意事項注意事項

您的電腦可能會在下列說明中,以不同名稱或位置顯示某些 Visual Studio 使用者介面項目。 您所擁有的 Visual Studio 版本以及使用的設定會決定這些項目。 如需詳細資訊,請參閱 Visual Studio 設定

若要建立要部署的 Web 瀏覽器應用程式

  1. 在 [檔案] 功能表上,指向 [新增],然後按一下 [專案]。

  2. 按一下 [Windows Form 應用程式]。

  3. 在 [名稱] 中,輸入 BrowserSample,然後按一下 [確定]。

  4. 在 [檢視] 功能表上,按一下 [工具箱]。

  5. 展開 [所有 Windows Form],並將 [Panel] 控制項拖曳至表單左上角。

  6. 在 [表單設計工具] 中,將 [TextBox] 控制項和 [Button] 控制項拖曳至 [Panel] 控制項。

  7. 在 [表單設計工具] 中,將 [WebBrowser] 控制項拖曳至 [Panel] 之下。

  8. 展開表單大小,以放入所有控制項。

  9. 在 [表單設計工具] 中,按一下 [Panel] 控制項。

  10. 在 [屬性] 視窗中,將 [版面配置] 下的 [Dock] 屬性變更為 [Top]。

  11. 在 [表單設計工具] 中,按一下 [WebBrowser] 控制項。

  12. 在 [屬性] 視窗中,將 [版面配置] 下的 [Dock] 屬性變更為 [Fill]。

  13. 在 [表單設計工具] 中,按一下 [Button] 控制項。

  14. 在 [屬性] 視窗中,將 [外觀] 下的 [Text] 屬性變更為 [移至]。

  15. 根據您的偏好調整 [Form]、[Panel]、[Textbox]、[Button] 和 [WebBrowser] 的大小。

  16. 在 [表單設計工具] 中,按兩下 [移至] 按鈕。

    Form1 程式碼檔的程式碼檢視隨即出現。

  17. 加入下列程式碼,將 Web 瀏覽功能加入至應用程式。 [TextBox] 控制項中的文字是 [WebBrowser] 控制項的位址列,而動作會在您按一下 [移至] 按鈕時發生。

    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. 若要測試瀏覽器,請按 F5。

    表單隨即開啟。

  19. 在文字方塊中,輸入 https://www.microsoft.com,然後按一下 [移至]。

    Microsoft 網站隨即出現。

若要建立自訂動作類別

  1. 在 [檔案] 功能表上指向 [加入],然後按一下 [新增專案]。

  2. 在 [加入新的專案] 對話方塊中,按一下 [Windows],然後按一下 [類別庫]。

  3. 在 [名稱] 方塊中,輸入 NGenCustomAction,然後按一下 [確定]。

  4. 按一下 [專案] 功能表上的 [加入新項目]。

  5. 在 [加入新項目] 對話方塊中,按一下 [一般],然後按一下 [安裝程式類別]。 在 [名稱] 方塊中輸入 NGenCustomAction,然後按一下 [加入]。

    注意事項注意事項

    確定您已加入 [安裝程式類別],否則程式碼檔將不會包含必要的 using 陳述式。

  6. 在 [方案總管] 中,刪除 NGenCustomAction 專案中的 Class1 程式碼檔。

若要新增程式碼至自訂動作

  1. 以滑鼠右鍵按一下 [方案總管] (或設計介面) 中的 NGenCustomAction 程式碼檔,然後按一下 [檢視程式碼] 以開啟 [程式碼編輯器]。 將下列程式碼加入至模組頂端。

    Imports System.IO
    Imports System.Diagnostics
    
    using System.IO;
    using System.Diagnostics;
    
  2. 將類別宣告更新為繼承自 System.Configuration.Install.Installer 類別。

    Inherits System.Configuration.Install.Installer
    
    : System.Configuration.Install.Installer
    
  3. 在 NGenCustomAction 程式碼檔中,加入下列 Helper 方法,以產生任何組件的原生映像程式碼檔。

        <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. 在 NGenCustomAction 程式碼檔中,加入下列程序以覆寫基底類別的 Install、Commit、Rollback 和 Uninstall 程序。

    <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");
    }
    

若要為瀏覽器範例應用程式加入部署專案

  1. 在 [檔案] 功能表上指向 [加入],然後按一下 [新增專案]。

  2. 在 [加入新的專案] 對話方塊中,依序展開 [其他專案類型] 和 [安裝和部署專案],按一下 [Visual Studio Installer],然後按一下 [安裝專案]。

  3. 在 [名稱] 方塊中輸入 Browser Sample Installer,然後按一下 [確定]。

  4. 在 [檔案系統編輯器] 中選取 [應用程式資料夾]。 按一下 [執行] 功能表上的 [加入]。

    [加入專案輸出群組] 對話方塊隨即出現。

  5. 在 [專案] 下拉式方塊中,選取 [BrowserSample],按一下 [專案輸出],然後按一下 [確定]。

  6. 在 [檔案系統編輯器] 中選取 [應用程式資料夾]。 按一下 [執行] 功能表上的 [加入]。

    [加入專案輸出群組] 對話方塊隨即出現。

  7. 在 [專案] 下拉式方塊中,選取 [NGenCustomAction],按一下 [專案輸出],然後按一下 [確定]。

若要將 NGEN 自訂動作加入至安裝專案

  1. 在 [方案總管] 中,按一下 [Browser Sample Installer] 專案。

  2. 在 [檢視] 功能表中指向 [編輯器],然後按一下 [自訂動作]。

  3. 在 [自訂動作編輯器] 中選取 [自訂動作] 節點。

  4. 在 [動作] 功能表上選擇 [加入自訂動作]。

  5. 在 [選取專案中項目] 對話方塊中,按兩下 [應用程式資料夾],按一下 [來自 NGenCustomAction 的主要輸出 (作用中)],然後按一下 [確定]。

    NGen 自訂動作隨即加入至全部四個自訂動作節點中。

  6. 在 [安裝] 節點中,按一下 [來自 NGenCustomAction 的主要輸出 (作用中)]。

  7. 在 [屬性] 視窗中,將 [CustomActionData] 屬性變更為 /Args="[TARGETDIR]BrowserSample.exe"。括上引號。

    注意事項注意事項

    [TARGETDIR] 屬性是所安裝可執行檔的位置。 自訂動作會使用 ngen.exe 將已安裝的可執行檔轉換為原生映像。

  8. 在 [方案總管] 中,按一下 [Browser Sample Installer] 安裝專案。

  9. 在 [建置] 功能表中,按一下 [建置 Browser Sample Installer]。

若要確認機器碼產生

  1. 巡覽至安裝資料夾並尋找 BrowserSample.exe 檔案。 例如 %PROGRAMFILES%\CompanyName\Brower Sample Installer\BrowserSample.exe。

  2. 在 Visual Studio 命令提示字元中,執行下列程式碼,確認可執行檔已先行編譯為機器碼:

    ngen.exe display FullPathToExe
    

    例如,您可以執行下列命令:

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

    命令輸出隨即出現。

    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>
    
    注意事項注意事項

    如果 ngen.exe 未顯示原生映像,您可以尋找下列其中一個目錄中的 ngen 記錄檔:

    %SystemRoot%\Microsoft.NET\Framework\v<CLR 版本> %SystemRoot%\Microsoft.NET\Framework64\v<CLR 版本>

    ngen.log 檔案是最新的疑難排解記錄檔。

請參閱

參考

CustomActionData 屬性

Ngen.exe (原生映像產生器)

概念

Managed 執行程序

其他資源

部署中的自訂動作管理