一、前言 2017年最後幾天,你們都高高興興的跨年,博主還在加班製作.net安裝包。因為年前要出來第一版的安裝包,所以博主是加班加點啊。本來想用VS自帶的製作工具,不過用過的人都知道,真是非常好(tong)用(ku),各種包需要單獨下載不說,界面也不美觀,所以決定棄用之。同事推薦用Advanced ...
一、前言
2017年最後幾天,你們都高高興興的跨年,博主還在加班製作.net安裝包。因為年前要出來第一版的安裝包,所以博主是加班加點啊。本來想用VS自帶的製作工具,不過用過的人都知道,真是非常好(tong)用(ku),各種包需要單獨下載不說,界面也不美觀,所以決定棄用之。同事推薦用Advanced Installer,不過同事也是很久不用了,記不起來具體用法。所以博主是邊摸索邊前進,所以不免跳進坑裡,為了避免後來人跳進同樣的坑裡,作文以記之。
好了,不說廢話,正文開始!
二、畫流程圖
俗話說的好,“磨刀不誤砍柴工”!
首先強調一點,我們要先弄清楚我們每一步要做什麼,這樣接下來在製作安裝包時才能條理清晰,有條不紊,不容易犯錯。
比如我們要判斷客戶機器上是否安裝.net framework3.5及以上版本,是否安裝IIS,是否安裝SQL Server2005及以上版本資料庫等等。
我這個項目的流程圖如下:
Tips1:開始之前最好先畫流程圖
三、開始製作
有了流程圖,只需按部就班!關於Advanced Installer的基礎用法,網上有很多的資料,官網也有幫助文檔,這裡就不贅述了。由於要用到自定義安裝包的過程,需要新建對話框,博主用了企業模板,Advanced Installer的版本是14.5.2,也是最新的版本。
1、選擇模板
首先新建模板裡面選擇Enterprise,並選擇語言(預設為中文),然後創建項目:
Tips2:如果安裝包中需要自定義對話框,則需要選擇Enterprise版。
2、設置基本信息
Name即為該安裝包的名稱,公司就是你所在的公司啦,還有版本信息等等,這個很簡單。
3、設置預設安裝路徑
點擊Package Definition->Install Parameters,填寫預設安裝路徑。
Application folder預設的內容是這樣:“[ProgramFilesFolder][Manufacturer]\[ProductName]”, 這個內容表示安裝時預設的安裝路徑:
[ProgramFilesFolder]表示文件夾,這裡為D:\Program Files(x86)。
[Manufacturer]表示公司名稱,這裡為Landsoft。
[ProductName]表示產品名稱,這裡為LandaV9。
4、設置安裝條件
點擊Requirements->Launch Conditions->Software,勾選相應的條件。這裡根據流程圖所示,我應該勾選.Net Framework、IIS以及SQL Server。註意這裡的條件指的是最低條件,比如我這裡SQL Server選的是2005,即客戶機器上應該裝有2005及以上版本的SQL Server,如果沒有裝,則會提示沒有安裝SQL2005。
這裡還有系統條件即要求客戶機器是win7還是winxp等等。如果還有更多的條件,Custom裡面可以自定義。
5、添加文件或文件夾
點擊Resources->Files and Folders,在Application Folders上右鍵,選擇Add Folder或者Add Files,這裡我添加了5個文件夾,用於後續操作。
6、自定義對話框(Dialog)
新建對話框之前可以在Themes中選擇主題和樣式。
點擊User Interface->Dialogs,在FolderDlg上右鍵,選擇Add Dialog是添加Advanced Installer中自定義的對話框,選擇New Dialog是新增一個空的對話框,
然後我們可自行在上面定義內容:
新建對話框後,可以拖出安裝過程中dialog的外觀,這個對於我們.Net開發人員來說,應該是小Case吧,看一下效果:
可以對文本框設置預設值:
Tips3:文本框中的屬性名,不要修改。如果修改會有大問題,至於什麼問題,後面再說!
由於我們需要設置連接字元串,所以需要客戶設置資料庫的相關信息:
選擇Add Dialog後,在彈出框中選擇SQLServerConnentionDlg
效果如下:
最後再新建一個對話框,用於部署項目到IIS所需要的條件:
同樣可以設置網站名稱和埠號:根據流程圖,這裡的預設值需要分別設置為Mango和8001,用戶可以自行修改。
到這裡新建對話框告一段落。
7、設置必填驗證
就拿上面這個對話框為例,雖然我們設置的有預設值,但是客戶在安裝過程中不小心給刪掉了,又沒有填寫,恰巧又點了下一步,這樣的話,安裝過程中會有問題。所以我們要做必填驗證,即文本框中沒有值,則“下一步”按鈕不可用,有值才可用。
所以選擇“下一步”,關註下方的“Control Conditions”:
點擊New按鈕在新彈出的界面中在Condition中填寫“NOT EDIT_1_DROP OR NOT EDIT_1_DROP_1”,在Action中選擇Disable。
EDIT_1_DROP和EDIT_1_DROP_1就是網站名稱和埠號,前面加NOT的意思就是,如果這兩個文本框中任意一個沒有填寫,則按鈕不可用(Disable)。
同理再添加一個“EDIT_1_DROP AND EDIT_1_DROP_1”,在Action中選擇Enable。即都填內容了,則按鈕可用。這樣就對控制項做了必填驗證。是不是很簡單呢!
8、設置桌面快捷方式
根據流程圖所示,安裝結束後,需要在桌面生成快捷防方式。所以接下來,我們就來做這件事:
首先來到Files and Folders選項卡,在Application Shortcut Folder上面右鍵 選擇“New Shortcut”,彈出如下界面:
在這個框里主要設置快捷方式的Name和描述以及圖標(這個圖標,可以選擇.exe文件)。點擊OK,就會在Application Shortcut Folder中顯示這樣一條信息。
但是先別急,如果僅僅是這樣的話,快捷方式是不起作用的。因為我們還沒有設置快捷方式對應的可執行文件。
雙擊這條信息,在彈出的對話框中設置Shortcut Target。
看到這,肯定有人有疑問?既然這樣為什麼不在新增快捷方式的時候一起設置呢?
因為在新增的時候,Shortcut target這個文本框中的內容不能修改。這個很坑爹,博主也試了好久才試出來的。
最後,將這個信息拖到Desktop裡面即可,安裝完畢後,就會在桌面顯示這個快捷方式。
四、設置IIS網站的網站名、埠號
在上面對話框的最後一步中,我們記住網站名稱的和埠號的文本框的屬性名,然後來到IIS選項卡中:
首先新增一個應用程式池,名稱即為網站名稱文本框的屬性名,這裡為EDIT_1_PROP,在Advanced Installer裡面,使用中括弧[]將控制項的屬性名括起來表示變數的概念。
在Basic Pool Settings中設置程式池的啟動模式為總是啟動,勾選立即啟動程式池覆選框,framework版本選擇為4.0,托管模式選擇為集成。
在Identity中設置應用程式池表示為ApplicationPoolIdentity。
應用程式池設置好之後,再來設置站點:
新建一個站點名稱同樣為EDIT_1_PROP,在Basic Site Setting中設置Name和文件路徑。
在Bindings/SSL中設置埠號,IP地址選擇全部未分配。
在Application Pool中選擇剛剛新建的應用程式池。
到這裡IIS這一塊就設置好了。
安裝過程中,Advanced Installer就會自動的將網站部署好。這個真的是很牛很強大!不得不佩服人家做的就是好!
五、兩種方式設置config文件
1、直接在Advanced Installer中設置
在添加文件的時候,如果有xml類型的文件,會有這樣的提示:
這時候我們勾選需要修改配置的文件,點擊ok,這樣就可以直接在Advanced Installer中修改。
找到需要修改的節點,直接有文本框的屬性替換掉就可以:
這樣,在安裝過程中就會將config文件中的相應的節點替換為客戶輸入的值。
還記得Tips3嗎?我們說過如果修改文本框的屬性名之後,那麼這樣設置之後,config中的值不會設置為客戶輸入的值,會始終是文本框中設置的預設值。
切記切記!!!重要的事情三個嘆號!
2、使用自定義的dll文件
關於這點請見第六小節。
六、自定義dll
點擊Custome Behavior->Custom Actions,選擇.Net Installer Class action。這時會讓你選擇文件中的dll文件。
當然了,在此之前,請打開你的Visual Studio,新建一個類庫項目,這裡命名為InstallLandaV9ServiceT,然後新建一個安裝程式類,重寫Install方法。
到這裡,我們先暫停一下,問一下自己:在程式中怎麼接收從Advanced Installer傳過來的參數呢?
假如此時我們已經將這個dll加入到Advanced Installer中,在Installer Class Paramters中可以添加參數。
比如將文件路徑傳到後臺,可以這樣添加:Name為FilePath,Value為[APPDIR]\。
這裡有地方需要註意,傳遞文件路徑時,Value為[APPDIR]\,這個"\"請不要漏掉了。
Tips4:傳遞文件路徑時,Value為[APPDIR]\,這個"\"請不要漏掉了。
其他參數的Value,需要設置為對應文本框的屬性名稱,格式為:[屬性名]。
下麵來看一看代碼:
public override void Install(IDictionary stateSaver) { Parameters configParms = new Parameters(); configParms.FilePath = Context.Parameters["FilePath"]; configParms.ServerPath = Context.Parameters["ServerPath"]; configParms.ClientPath = Context.Parameters["ClientPath"]; configParms.DataSource = Context.Parameters["DataSource"]; configParms.UserId = Context.Parameters["UserId"]; configParms.Password = Context.Parameters["Password"]; new Operators().UpdateLandaV9Config(configParms); base.Install(stateSaver); }
這裡主要接收從Advanced Installer中傳過來的參數,接著在Operators類中更新配置文件。
還記得Tips3嗎?如果在那裡修改的屬性名,那麼這裡接收的參數也是文本框的預設值。
這裡面主要幹了三件事,獲取連接字元串,更新連接字元串,安裝服務
public void UpdateLandaV9Config(Parameters configParms) { string filePath = Path.Combine(configParms.FilePath, "LandaV9Service", "LandaEntryInfoService.exe.config"); string connectionString = this.GetConnectionString(configParms); this.UpdateConnections(filePath, connectionString);this.InstallService(Path.Combine(configParms.FilePath, "LandaV9Service")); }
還記得Tips4嗎?如果在傳遞文件路徑的時候只是寫[APPDIR],而不是[APPDIR]\,那麼程式運行到這裡的時候,會拋“FileNotFound”異常!
下來來看一下具體的代碼:
/// <summary> /// 獲取連接字元串 /// </summary> /// <param name="op"></param> /// <returns></returns> public string GetConnectionString(Parameters op) { return string.Format("Data Source={0};Initial Catalog=LandaEntryManager;Persist Security Info=True;User ID={1};Password={2}", op.DataSource, op.UserId, op.Password); } /// <summary> /// 更新連接字元串 /// </summary> /// <param name="filePath"></param> /// <param name="conn"></param> public void UpdateConnections(string filePath, string conn) { XmlDocument xmlDocument = new XmlDocument(); xmlDocument.Load(filePath); XmlElement xmlElement = (XmlElement)xmlDocument.SelectSingleNode("/configuration/connectionStrings/add[@name='LandaEntryManager']"); if (xmlElement != null) xmlElement.SetAttribute("connectionString", conn); xmlDocument.Save(filePath); }
再來看安裝服務:
/// <summary> /// 安裝服務 /// </summary> /// <param name="filePath"></param> public void InstallService(string filePath) { Environment.CurrentDirectory = filePath; Process process = new Process(); process.StartInfo.UseShellExecute = false; process.StartInfo.FileName = "Install.bat"; process.StartInfo.CreateNoWindow = true; process.StartInfo.Verb = "runas"; //主要設置為以管理員啟動 process.Start(); }
有安裝就有啟動,可是如果緊跟其後寫啟動服務,會提示找不到服務,安裝程式就會出錯。
博主想了一個辦法,重寫OnAfterInstall方法,在這個方法裡面寫啟動服務:
/// <summary> /// 重啟服務 /// </summary> /// <param name="savedState"></param> protected override void OnAfterInstall(IDictionary savedState) { ServiceController serviceController = new ServiceController("LandaInformationServiceV9"); serviceController.Start(); base.OnAfterInstall(savedState); }
這樣就沒問題了!
在這個程式集裡面可以自定義你想做的其他事情,比如,還原資料庫等等。
七、後記
本次教程到此結束,這也是博主在這幾天假期摸索出來的,如果有不當之處,盡請指正!
附上Advanced Installer的官網地址:https://www.advancedinstaller.com/。
希望本文對你有所幫助。如果你覺得本文能夠幫助你,就點個贊吧。你的支持是博主繼續堅持的不懈動力。