VS 自帶MSI安裝程序注意事項

 
安裝製作注意事項:
1.在四)創建自定義安裝對話框 的EditProperty中所有的內容無論你輸入小寫或大寫都是以大寫形式出現的,很容易讓人誤解爲這裏不區分大小,但事實上是區分的,所以變量都是大寫,所以在五).創建自定義操作時 “/dbname=[CUSTOMTEXTA1] /server=[CUSTOMTEXTA2] /user=[CUSTOMTEXTA3] /pwd=[CUSTOMTEXTA4] /targetdir="[TARGETDIR]/,[ ]裏的內容都是大寫。
因爲所有的狀態只有當您調用 base.Install(StateSaver) 時,IDictionary 對象纔會反映過程的當前狀態,所以你所有訪問this.Context.Parameters["targetdir"]等的信息要在調用 base.Install(StateSaver)之後用。否則要出錯的。
2.方法:ExecuteSql(strDBName,GetSql("sql.txt"));  的sql.txt裏的面的Sql語句中:如果是直接從Sql2k or yukon裏導出的則要將其中的Go 去掉,否則執行時要報錯
3.如何調試自定義操作/安裝程序類?

可以使用下列方法之一:

在您的代碼中添加對 System.Diagnostics.Debugger.Launch 的調用。該方法會打開實時調試,並允許您將新的調試器附加到您的代碼。

在您的代碼中添加對 MessageBox.Show("Debug Me") 的調用。顯示消息框時,使用 Visual Studio 附加到 MessageBox 進程。然後將斷點(對於 Visual C# 項目)或停止點(對於 Visual Basic 項目)放入代碼中。

將調試首選項設置爲啓動 InstallUtil.exe(位於 /winnt/Microsoft.net/Framework/version )並將其作爲參數傳遞給程序集。按 F5 時,命中斷點。InstallUtil.exe 運行自定義操作的方式將和 MSI 一樣。

4.CustomActionData 屬性的格式取決於自定義操作的類型。

對於作爲安裝組件的自定義操作(ProjectInstaller 類),“CustomActionData”屬性採用 /name=value 形式。其中的每個名稱都必須是唯一的,並且僅有一個值。多個值之間必須用一個空格隔開:/name1=value1 /name2=value2 。如果值本身有一個空格,則必須在該值兩側加上引號:/name="a value"

使用加括號的語法:/name=[PROPERTYNAME] ,可以傳遞 Windows Installer 屬性。對於像“[TARGETDIR]”這樣返回目錄的 Windows Installer 屬性,除了加括號外,還必須加引號和尾部反斜槓:/name="[TARGETDIR]/"

注意

爲了使自定義操作被視爲安裝組件,必須將“InstallerClass”屬性設置爲“true”。

5.Windows Installer 自動管理部署中的多數錯誤處理;但是,自定義操作中的錯誤可以導致安裝程序失敗。所有自定義操作都包含代碼;就像所有代碼一樣,錯誤處理是過程不可缺少的 一部分。例如,如果某個自定義操作包含打開某個文件的代碼,但缺少此文件,則需要有一個錯誤處理程序將該錯誤報告給 Windows Installer ,以便安裝可以回滾。
// Uses System.IO and System.Configuration.Install
FileInfo Info = new FileInfo("MyFile.txt");
if (Info.Exists == false)
throw new InstallException("File does not exist");
具體的步驟請參見下面: 
安裝的步驟出處:http://blog.csdn.net/lyb_abiandbel/

 

一).創建部署項目

1. 在“文件”菜單上指向“添加項目”,然後選擇“新建項目”。

2. 在“添加新項目”對話框中,選擇“項目類型”窗格中的“安裝和部署項目”,然後選擇“模板”窗格中的“安裝項目”。在“名稱”框中鍵入 setup1。

3. 單擊“確定”關閉對話框。
 
4. 項目被添加到解決方案資源管理器中,並且文件系統編輯器打開。
 
5. 在“屬性”窗口中,選擇 ProductName 屬性,並鍵入 信息管理系統 。
 
二).將 主程序 項目的輸出添加到部署項目中
 
1. 在“文件系統編輯器”中,選擇“應用程序文件夾”。在“操作”菜單上,指向“添加”,然後選擇“項目輸出”。
 
2. 在“添加項目輸出組”對話框中,選擇“項目”下拉列表中的“你的程序”。
 
3. 單擊“確定”關閉對話框。
 
4. 從列表中選擇“主輸出”和“內容文件”組,然後單擊“確定”。
 
三).創建安裝程序類
 
1. 在“文件”菜單上指向“新建”,然後選擇“項目”。
 
2. 在“新建項目”對話框中,選擇“項目類型”窗格中的“Visual Basic 項目”,然後選擇“模板”窗格中的“類庫”。在“名稱”框中鍵入 installDB。
 
3. 單擊“打開”關閉對話框。
 
4. 從“項目”菜單中選擇“添加新項”。
 
5. 在“添加新項”對話框中選擇“安裝程序類”。在“名稱”框中鍵入 installDB。
 
6. 單擊“確定”關閉對話框。
 
7. 詳細代碼附後。
 
四).創建自定義安裝對話框
 
1. 在解決方案資源管理器中選擇“setup1”項目。在“視圖”菜單上指向“編輯器”,然後選擇“用戶界面”。
2. 在用戶界面編輯器中,選擇“安裝”下的“啓動”節點。在“操作”菜單上,選擇“添加對話框”。
3. 在“添加對話框”對話框中,選擇“許可協議”對話框,然後單擊“確定”關閉對話框。
4. 在“添加對話框”對話框中,選擇“文本框 (A)”對話框,然後單擊“確定”關閉對話框。
5. 在“操作”菜單上,選擇“上移”。重複此步驟,直到“文本框 (A)”對話框位於“安裝文件夾”節點之上。
6. 在“屬性”窗口中,選擇 BannerText 屬性並鍵入:安裝數據庫.
7. 選擇 BodyText 屬性並鍵入:安裝程序將在目標機器上安裝數據庫
8. 選擇 Edit1Label 屬性並鍵入:數據庫名稱:
9. 選擇 Edit1Property 屬性並鍵入 CUSTOMTEXTA1
10. 選擇 Edit1Value 屬性並鍵入:dbservers
11. 選擇 Edit2Label 屬性並鍵入:服務器名:
12. 選擇 Edit2Property 屬性並鍵入 CUSTOMTEXTA2
13. 選擇 Edit2Value 屬性並鍵入:(local)
14. 選擇 Edit3Label 屬性並鍵入:用戶名:
15. 選擇 Edit3Value 屬性並鍵入:sa
16. 選擇 Edit3Property 屬性並鍵入 CUSTOMTEXTA3
17. 選擇 Edit4Label 屬性並鍵入:密碼:
18. 選擇 Edit4Property 屬性並鍵入 CUSTOMTEXTA4
19. 選擇 Edit2Visible、Edit3Visible 和 Edit4Visible 屬性,並將它們設置爲 true
 
五).創建自定義操作
 
1. 在解決方案資源管理器中選擇“setup1”項目。在“視圖”菜單上指向“編輯器”,然後選擇“自定義操作”。
2. 在自定義操作編輯器中選擇“安裝”節點。在“操作”菜單上,選擇“添加自定義操作”。
3. 在“選擇項目中的項”對話框中,雙擊“應用程序文件夾”。
4. 選擇“主輸出來自 installDB(活動)”項,然後單擊“確定”關閉對話框。
5. 在“屬性”窗口中,選擇 CustomActionData 屬性並鍵入“/dbname=[CUSTOMTEXTA1] /server=[CUSTOMTEXTA2] /user=[CUSTOMTEXTA3] /pwd=[CUSTOMTEXTA4] /targetdir="[TARGETDIR]/"”。
 
附:/targetdir="[TARGETDIR]/"是安裝後的目標路徑,爲了在installDB類中獲得安裝後的路徑,我們設置此參數。
 
六).打包時加入卸載功能:
 
方法一:

1.在打包項目中添加文件msiexec.exe(一般可在c:/windows/system32/下找到)

2.在文件系統視圖中選擇應用程序文件夾,在msiexec.exe上按右鍵,選擇創建快捷方式,重命名快捷方式為"卸載".

3.更改此快捷方式的Arguments 爲"/x {產品id}",產品id的值為打包項目的ProductCode屬性值.
 
方法二:(推薦)

1.先生成安裝包,記下ProductCode(選擇解決方案資源管理器根目錄如setup1,再查看屬性標籤,不是右鍵中的屬性),下面要用到

2.用VS.net建立一個新的控制檯程序uninst.exe文件

'power by: landlordh

'for 2000,xp,2003

Module uninstall

Sub Main()

Dim myProcess As Process = New Process

If System.Environment.OSVersion.ToString.IndexOf("NT 5") Then

myProcess.Start("msiexec", "/X{2B65D4A9-C146-4808-AB4B-321FB0779559}")  '改爲自己的ProductCode

End If

myProcess.Close()

End Sub

End Module


3.將控制檯程序BIN目錄的exe文件加入到打包程序文件中,在程序組創建uninst.exe的快捷方式
 
installdb.vb類,要添加引用 system.configuration.install.dll :

using System;

using System.Collections;

using System.ComponentModel;

using System.Configuration.Install;

using System.Reflection;

using System.IO;

using System.Data;

using System.Data.SqlClient;
namespace install

{

/// <summary>

/// Installer1 的摘要說明。

/// </summary>

[RunInstaller(true)]

public class Installer1 : System.Configuration.Install.Installer

{

/// <summary>

/// 必需的設計器變量。

/// </summary>

private System.ComponentModel.Container components = null;
  public Installer1()

{

// 該調用是設計器所必需的。

InitializeComponent();
   // TODO: 在 InitializeComponent 調用後添加任何初始化

}
  /// <summary>

/// 清理所有正在使用的資源。

/// </summary>

protected override void Dispose( bool disposing )

{

if( disposing )

{

if(components != null)

{

components.Dispose();

}

}

base.Dispose( disposing );

}


#region 組件設計器生成的代碼

/// <summary>

/// 設計器支持所需的方法 - 不要使用代碼編輯器修改

/// 此方法的內容。

/// </summary>

private void InitializeComponent()

{

components = new System.ComponentModel.Container();

}

#endregion
  private  string GetSql(string Name) 



//   //調用osql執行腳本

//

//   System.Diagnostics.Process sqlProcess = new System.Diagnostics.Process();

//

//   sqlProcess.StartInfo.FileName = "osql.exe";

//

//   sqlProcess.StartInfo.Arguments = String.Format(" -U {0} -P {1} -d {2} -i {3}db.sql", this.Context.Parameters["user"], this.Context.Parameters["pwd"],"master", this.Context.Parameters["targetdir"]);

//

//   sqlProcess.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;

//

//   sqlProcess.Start();

//

//   sqlProcess.WaitForExit() ;//等待執行

//

//   sqlProcess.Close();

try 



//    Assembly Asm = Assembly.GetExecutingAssembly();

//    System.IO.FileInfo FileInfo = new System.IO.FileInfo(Asm.Location);

//    string path=FileInfo.DirectoryName+@"/"+Name ;

string path=this.Context.Parameters["targetdir"]+Name;

FileStream fs=new FileStream(path,FileMode.Open,FileAccess.Read,FileShare.Read);

StreamReader reader = new StreamReader(fs,System.Text.Encoding.Default); 

//System.Text.Encoding.ASCII;

return reader.ReadToEnd(); 
   } 

catch (Exception ex) 



Console.Write("In GetSql:"+ex.Message); 

throw ex; 



  private void ExecuteSql(string DataBaseName,string Sql) 

{

SqlConnection sqlConnection1=new SqlConnection();

sqlConnection1.ConnectionString =string.Format("server={0}; user id={1}; password={2}; Database=master",this.Context.Parameters["server"],this.Context.Parameters["user"],this.Context.Parameters["pwd"]);

System.Data.SqlClient.SqlCommand Command = new System.Data.SqlClient.SqlCommand(Sql,sqlConnection1); 

try 

{

Command.Connection.Open(); 

Command.Connection.ChangeDatabase(DataBaseName); 



Command.ExecuteNonQuery(); 



catch(Exception ex) 



Console.Write("In exception handler :"+ex.Message); 

}

finally 



Command.Connection.Close(); 





protected void AddDBTable(string strDBName) 



try 

{      

ExecuteSql("master","CREATE DATABASE "+ strDBName);

ExecuteSql(strDBName,GetSql("sql.txt"));  

ExecuteSql("master","exec sp_addlogin 'myoamaster','myoamaster','"+strDBName+"',Null,Null");

ExecuteSql(strDBName,"EXEC sp_grantdbaccess 'myoamaster', 'myoamaster'");

ExecuteSql(strDBName,"exec sp_addrolemember 'db_owner','myoamaster'");



catch(Exception ex) 



Console.Write("In exception handler :"+ex.Message); 



  public override void Install(System.Collections.IDictionary stateSaver) 



base.Install(stateSaver); 

AddDBTable(this.Context.Parameters["dbname"]); 



}

}
這裏有個sql.txt是數據庫的sql腳本,當然可以調用osql來執行sql腳本,其實是一樣的。
打包的時候必須把sql.txt文件加進來,否則不會執行。
如果你想附加數據庫的mdf文件和ldf文件,用下面這段程序:
private void CreateDataBase(string strSql,string DataName,string strMdf,string strLdf)

{

String str;

SqlConnection myConn = new SqlConnection (strSql);
   //EXEC sp_detach_db @dbname = 'BX_FreightMileage_2'//需要先將數據庫分離出來

str = "EXEC sp_attach_db @dbname = '"+ DataName +"', @filename1 = '"+ strMdf +"',@filename2='"+strLdf+"'";
   SqlCommand myCommand = new SqlCommand(str, myConn);



myConn.Open();

myCommand.ExecuteNonQuery();

myConn.Close();



}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章