本文詳細記錄如何使用 Visual Studio **安裝部署專案** (Setup Project) 打包應用程式,並在安裝過程中自動建立/初始化 SQL Server 資料庫。涵蓋自定義安裝介面、自定義動作、自定義安裝類別、卸載捷徑建立等完整流程。
setup1ProductName = "資訊管理系統"installDB (VB.NET 或 C# 均可)installDB.csInstall 覆寫方法,執行資料庫建立腳本在「使用者介面」編輯器 → 「安裝」→「開始」節點右鍵「加入對話框」:
| 屬性 | 值 |
|---|---|
| BannerText | 安裝資料庫 |
| BodyText | 安裝程式將在目標機器上安裝資料庫 |
| Edit1Label | 資料庫名稱: |
| Edit1Property | CUSTOMTEXTA1 |
| Edit1Value | dbservers |
| Edit2Label | 伺服器名稱: |
| Edit2Property | CUSTOMTEXTA2 |
| Edit2Value | (local) |
| Edit3Label | 使用者名稱: |
| Edit3Property | CUSTOMTEXTA3 |
| Edit3Value | sa |
| Edit4Label | 密碼: |
| Edit4Property | CUSTOMTEXTA4 |
| Edit2Visible/3/4 | True |
CustomActionData 屬性:/dbname=[CUSTOMTEXTA1] /server=[CUSTOMTEXTA2] /user=[CUSTOMTEXTA3] /pwd=[CUSTOMTEXTA4] /targetdir="[TARGETDIR]\"
/targetdir 為安裝後目標路徑,供安裝類別讀取 SQL 腳本檔案。
using System;
using System.Collections;
using System.ComponentModel;
using System.Configuration.Install;
using System.IO;
using System.Data.SqlClient;
using System.Reflection;
namespace install
{
[RunInstaller(true)]
public class Installer1 : Installer
{
public override void Install(IDictionary stateSaver)
{
base.Install(stateSaver);
AddDBTable(Context.Parameters["dbname"]);
}
private string GetSql(string fileName)
{
// 從安裝目錄讀取 sql.txt 腳本
string path = Path.Combine(Context.Parameters["targetdir"], fileName);
return File.ReadAllText(path, Encoding.Default);
}
private void ExecuteSql(string dbName, string sql)
{
using (var conn = new SqlConnection(
$"server={Context.Parameters["server"]}; user id={Context.Parameters["user"]}; password={Context.Parameters["pwd"]}; Database={dbName}"))
using (var cmd = new SqlCommand(sql, conn))
{
conn.Open();
cmd.ExecuteNonQuery();
}
}
private void AddDBTable(string dbName)
{
try
{
// 1. 建立資料庫
ExecuteSql("master", $"CREATE DATABASE [{dbName}]");
// 2. 執行結構腳本
ExecuteSql(dbName, GetSql("sql.txt"));
// 3. 建立登入與使用者對應
ExecuteSql("master", $"EXEC sp_addlogin 'myoamaster','myoamaster','{dbName}'");
ExecuteSql(dbName, $"EXEC sp_grantdbaccess 'myoamaster', 'myoamaster'");
ExecuteSql(dbName, $"EXEC sp_addrolemember 'db_owner','myoamaster'");
}
catch (Exception ex)
{
// 安裝失敗會自動回滾
throw new InstallException("資料庫初始化失敗: " + ex.Message, ex);
}
}
}
}
msiexec.exe (通常在 C:\Windows\System32)/x {ProductCode} (ProductCode 見專案屬性)uninst.exe:Module uninstall
Sub Main()
Dim myProcess As New Process()
If Environment.OSVersion.ToString.IndexOf("NT 5") >= 0 Then
myProcess.Start("msiexec", "/X{你的 ProductCode}")
End If
myProcess.Close()
End Sub
End Module
uninst.exe 加入部署專案,建立捷徑private void AttachDatabase(string masterConnStr, string dbName, string mdfPath, string ldfPath)
{
string sql = $@"EXEC sp_attach_db @dbname = '{dbName}', @filename1 = '{mdfPath}', @filename2 = '{ldfPath}'";
using (var conn = new SqlConnection(masterConnStr))
using (var cmd = new SqlCommand(sql, conn))
{
conn.Open();
cmd.ExecuteNonQuery();
}
}
記得將 .mdf、.ldf 也加入部署專案的「應用程式資料夾」。
System.Configuration.Install.dll。Context.Parameters 取得自定義動作傳遞的參數。