2012年2月8日 星期三

建立Installer

要設計安裝程序,可以在 Visual Studion 中建立一個安裝專案,將應用程式專案打包成一個安裝檔後,再進行安裝。 另外也可以在應用程式專案中,自行加入一個安裝類別,再透過安裝工具 InstallUtil.exe ,將該組件安裝至系統。

建立標準安裝檔

如何建立標準安裝檔

使用.NET提供的安裝專案,可以輕鬆快速的建立Setup程式。底下示範如何建立安裝專案:

1.建立一個【應用程式專案】,取名為TestAP。(假設這個專案就是即將被做成安裝檔的專案)

2.加入一個【安裝專案】,取名為Setup1。

你可以在【安裝專案】的右鍵選單中檢視專案的檔案系統,檔案系統中預設會有下列三個項目:

  • 使用者的桌面:用來設定要在使用者的桌面建立哪些檔案,通常是捷徑。
  • 使用者的程式功能表:用來設定要在使用者的程式功能表建立哪些檔案,通常也是捷徑。
  • 應用程式資料夾:用來設定應用程式安裝目錄中的內容。

你也可以點選檔案系統根目錄上的右鍵選單,加入其他特殊資料夾

3.設定安裝專案的屬性。

上圖中,紅色框線的欄位是比較常用的,它們會出現在下圖的畫面中。

另外值的一提的,在應用程式資料夾的屬性有個 DefaultLocation ,就是參考專案屬性中的 [Manufacturer] 和 [ProductName] 設定值。

4.將【應用程式專案】加入到【安裝專案】中

在方案總管中,點選安裝專案,在右鍵選單中,點選「加入專案輸出」。等詢問視窗出現後,在專案選項中,選擇你要安裝的專案。

這個步驟完成後,你可以看到以下的內容,它表示我們要將【應用程式專案】產生的執行檔,安裝到指定的目錄中。 所以,如果你同時有其他專案的檔案要打包進來,就可以重複這個步驟。 或者你有特定的檔案要一併安裝進去,也可以在這裡做設定。

5.建置【安裝專案】

做完以下步驟,原則上就可以開始建置Setup1專案,以產生安裝檔。底下是一些額外功能,也可以參考參考。

如何建立一個捷徑

  • 點選【應用程式資料夾】,點選【主要輸出從XXX】,在右鍵選單中,建立一個捷徑,取名為TestApp。

如何讓安裝程式自動在桌面建立捷徑

  • 將上一步驟所建立的捷徑,拖拉至【使用者的桌面】。

如何讓安裝程式自動在開始功能表中建立捷徑

  • 在Setup1專案的檔案系統功能中,點選【目標電腦上的檔案系統】,在右鍵選單中,點選【加入特殊資料夾】,然後選擇【使用者的開始功能表(User's Start Menu)】。
  • 重複步驟5,再建一個捷徑,並將建立的捷徑拖拉至【使用者的開始功能表】。

如何設定捷徑的圖示

  • 先在【應用程式資料夾中】,加入圖示檔案
  • 點選【使用者的桌面】中的那個捷徑,在其屬性視窗中的Icon欄位,找到上一步驟的檔案。
  • 這樣子,安裝完之後,桌面就會有一個包含icon的捷徑。
  • 同樣的,若希望【開始功能表】中的捷徑也有圖示,照著做就可以。

建立客製化安裝檔

.NET 提供了 System.Configuration.Install.Installer 這個類別,用以建立自訂安裝程式。使用這個類別,必須遵守下列幾個步驟:

  1. 建立一個衍生類別,繼承自 Installer 類別。
  2. 在這個類別上頭加上 RunInstallerAttribute 屬性,並將值設為 true。 這個設定值是用來告訴系統,當組件安裝時,是否要叫用 Visual Studio Custom Action Installer 或 Installutil.exe 。
  3. 視實際需求,覆寫 InstallCommitRollbackUninstall 等方法,並撰寫程式碼。

下面例子將示範如何製作一個安裝檔,且符合以下功能:

  • 1.在安裝過程中,加入一個對話視窗,要求使用者輸入公司名稱及電話,並將這些資訊更新到應用程式的組態檔,以便應用程式執行時可讀取使用。
  • 2.在安裝進行時,在安裝目錄中產生一個檔案,檔名為 Log.txt。
  • 3.在安裝完成時,建立一個檔案 C:\Commit.txt。
  • 4.在安裝失敗時,建立一個檔案 C:\Rollback.txt。
  • 5.在安裝移除時,建立一個檔案 C:\Uninstall.txt,並將 Commit.txt、Rollback.txt 刪除。

1.建立一個【應用程式專案】,取名為TestAP,並加入一個【應用程式組態檔】,組態檔內容如下。(假設這個就是要被做成安裝檔的專案)

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="CopName" value=""/>
    <add key="CopTel" value=""/>
  </appSettings>
</configuration>

2 ~ 4 同建立標準安裝檔。

5.開啟【使用者介面編輯器】,點選【開始】,在右鍵選單中,點選【加入對話方塊】。等詢問視窗出現後,選擇【文字方塊(A)】,再按確定。(你可依實際需求,加入你要的對話方塊)

6.將文字方塊(A),拖拉至【確認安裝】之前。

7.點選【文字方塊(A)】,打開屬性視窗。

屬性視窗中的欄位設定,分別對應到右圖中這個安裝過程中的新增對話視窗,你可以在此做一些文字設定,如 BannerText、BodyText 等等.
另外文字方塊(A),預設有4個InputBox,對應到此處的 Edit1~Edit4 四個項目,你可以在此設定輸入方塊前的標題文字,若用不到的輸入方塊,可將其 Visible 屬性設成 False 即可。

底下步驟開始客製化程式

8.在TestAP專案中加入一個【安裝程式類別】,取名 myInstaller。

9.切換到安裝程式類別的檢視程式碼,配合案例需求,我們必須在專案中加入 System.Configulation 參考,以進行組態檔變更,並且引用以下命名空間:

using System.IO;
using System.Configuration;

10.開啟Setup1專案的【自訂動作編輯器】

11.在自訂動作編輯器的安裝項目中,利用右鍵選單【加入自訂動作】,完成對話視窗的設定,如下圖所示。

12.點選【安裝】項目底下的自訂動作,打開屬性設定視窗,在 CustomActionData 欄位輸入 /para1="[EDITA1]" /para1="[EDITA2]"

這裡比較要特別說明的是 CustomActionData,這是用來對應到使用者所輸入的資料,以便讓程式碼讀取
配合文字方塊(A)的樣式,所以可以設定4組參數,每一組使用一個空白隔開
/para1="[EDITA1]" /para1="[EDITA2] /para3="[EDITA2] /para4="[EDITA2]
para1~para4 是程式中,用來讀取參數的key值,可自行設定,只要程式碼使用一致即可。
EDITA1~EDITA2 是步驟7中 Edit?Property 欄位的值,也可任意設定,只要二邊一致即可。
如上設定,使用 Context.Parameters["para1"] 就可取得 EDITA1 這個TextBox的輸入資料。

13.修改 myInstaller 類別,內容如下

  using System;  using System.Collections;  using System.Collections.Generic;  using System.ComponentModel;  using System.Configuration.Install;  using System.IO;
using System.Configuration;
  namespace TestAP  {      [RunInstaller(true)]      public partial class myInstaller : Installer      {          public myInstaller()          {              InitializeComponent();          }            //覆寫原先的Install()方法          public override void Install(IDictionary savedState)          {              base.Install(savedState);                //取得安裝路徑              string InstallPath = Path.GetDirectoryName(Context.Parameters["assemblypath"]);                //建立Log檔              StreamWriter log = System.IO.File.CreateText(Path.Combine(InstallPath, "Log.txt"));  //在安裝目錄中,建立一個Log檔                //for debug              foreach (DictionaryEntry de in Context.Parameters)              {                  log.WriteLine("key:{0} value:{1}", de.Key, de.Value);              }                //開啟應用程式設定檔               var exeConfigurationFileMap = new ExeConfigurationFileMap();              exeConfigurationFileMap.ExeConfigFilename = Context.Parameters["assemblypath"] + ".config";              var config = ConfigurationManager.OpenMappedExeConfiguration(exeConfigurationFileMap, ConfigurationUserLevel.None);                //更新設定檔變數的值              config.AppSettings.Settings["CopName"].Value = Context.Parameters["COPNAME"];  //讀取使用者輸入的公司名稱              config.AppSettings.Settings["CopTel"].Value = Context.Parameters["COPTEL"];    //讀取使用者輸入的公司電話                //儲存              config.Save();              log.Close();                //測試 <a target='_blank' href='http://msdn.microsoft.com/zh-tw/library/system.configuration.install.installer.rollback'>Rollback</a> 區段              //throw new Exception("Rollback test");                // 有時候安裝過程,也常會同時註冊機碼              Registry.CurrentUser.CreateSubKey(@"Software\CustomKey");          }            //覆寫Uninstall(),刪除Install時建立的Log檔          public override void Uninstall(IDictionary savedState)          {              base.Uninstall(savedState);                //..do anything if necessary                if (File.Exists(@"C:\Rollback.txt"))                  File.Delete(@"C:\Rollback.txt");                if (File.Exists(@"C:\Commit.txt"))                  File.Delete(@"C:\Commit.txt");                System.IO.File.CreateText(@"C:\Uninstall.txt");          }            //覆寫Rollback()方法,刪除Install時建立的Log檔          public override void Rollback(IDictionary savedState)          {              base.Rollback(savedState);                //..do anything if necessary                System.IO.File.CreateText(@"C:\Rollback.txt");          }            //覆寫Commit()方法          public override void Commit(IDictionary savedState)          {              base.Commit(savedState);                //..do anything if necessary                System.IO.File.CreateText(@"C:\Commit.txt");          }        }  }  

14.分別在自訂動作功能裡的【認可】【復原】【解除安裝】項目底下,重複步驟10,

我們在步驟10的程式碼中,覆寫了Commit、Rollback、Uninstall方法,必須在此加入這些自訂動作,程式才會進入執行。

=>設定到此大功告成。

執行 setup,是否出現要求輸入公司資訊的視窗。
檢查設定檔,公司資訊是否已變更。
檢查安裝目錄,檔案Log.txt是否已建立。
檢查 C:\,檔案Commin.txt是否已建立。
執行 Uninstall,檢查檔案 Commin.txt 是否有被刪除。

啟動安裝程式

上面這個例子,我們在應用程式專案中加入了一個繼承自 Installer 的安裝類別,同時也建立一個安裝專案,以便設計一個自訂的安裝畫面,讀取使用者的公司名稱及電話。 若透過安裝專案進行安裝,安裝過程會將使用者輸入的資料帶入 Install 方法中,如果使用 InstallUtil.exe 工具安裝,依然會執行 Install 方法,就不會帶入使用者輸入的資料。 底下示範的是,如何使用 InstallUtil.exe 工具進行安裝。

在命令列中使用 InstallUtil.exe 工具安裝

InstallUtil.exe 這個工具會對應用程式中的組件進行反射(reflection),找出所有繼承 Installer 且具有 RunInstaller(true) 屬性的類別,然後執行其 Install 方法。

//安裝
InstallUtil myAssembly.exe

//移除安裝
InstallUtil /u myAssembly.exe

透過程式碼啟動安裝

若要以程式方式啟動安裝程式,可以使用 AssemblyInstallerComponentInstaller 類別。使用這二個類別時必須執行下列兩個步驟:

  • 建立其物件的執行個體。
  • 呼叫安裝程式中想要執行的方法
// 建立一個安裝類別的執行個體
AssemblyInstaller assInstaller = new AssemblyInstaller("Practice.exe", null);

// 使用新安裝內容
assInstaller.UseNewContext = true;

// 以下視需求,執行必要的方法:

// 執行 Install
assInstaller.Install(actions);

// 執行 Commit 
assInstaller.Commit(actions);

// 執行 Uninstall 
assInstaller.Uninstall(actions);

// 執行 Rollback 
assInstaller.Rollback(actions);

沒有留言:

張貼留言