// 1. 獲取網絡可見 SQL Server 列表
List<string> servers = new List<string>();
SQLDMO.Application sqlApp = new SQLDMO.ApplicationClass();
SQLDMO.NameList sqlServers = sqlApp.ListAvailableSQLServers();
for (int i = 1; i <= sqlServers.Count; i++) { // SQLDMO 集合 1-based
object srv = sqlServers.Item(i);
if (srv != null) servers.Add(srv.ToString());
}
// 2. 連接指定服務器獲取數據庫列表
List<string> databases = new List<string>();
foreach (string srvName in servers) {
SQLDMO.SQLServer srv = new SQLDMO.SQLServerClass();
srv.Connect(srvName, "sa", "123"); // 生產環境請用集成認證或配置文件
foreach (SQLDMO.Database db in srv.Databases) {
if (db.Name != null) databases.Add(db.Name);
}
srv.DisConnect();
}
// 3. 獲取存儲過程/表/視圖
SQLDMO.SQLServer srv2 = new SQLDMO.SQLServerClass();
srv2.Connect(cboServers.SelectedItem.ToString(), txtUser.Text, txtPassWord.Text);
for (int i = 1; i <= srv2.Databases.Count; i++) {
if (srv2.Databases.Item(i, "dbo").Name == cboDatabase.SelectedItem.ToString()) {
SQLDMO._Database db = srv2.Databases.Item(i, "dbo");
lstObjects.Items.Clear();
for (int j = 1; j <= db.StoredProcedures.Count; j++) {
lstObjects.Items.Add(db.StoredProcedures.Item(j, "dbo").Name);
}
break;
}
}
注意:SQLDMO 已停止更新,SQL Server 2012+ 不再包含,僅適用於 2000/2005/2008/R2 環境。
public class SqlLocator {
// P/Invoke 簽名
[DllImport("odbc32.dll")] private static extern short SQLAllocHandle(short hType, IntPtr inputHandle, out IntPtr outputHandle);
[DllImport("odbc32.dll")] private static extern short SQLSetEnvAttr(IntPtr henv, int attribute, IntPtr valuePtr, int strLength);
[DllImport("odbc32.dll")] private static extern short SQLFreeHandle(short hType, IntPtr handle);
[DllImport("odbc32.dll", CharSet = CharSet.Ansi)] private static extern short SQLBrowseConnect(IntPtr hconn, StringBuilder inString, short inStringLength, StringBuilder outString, short outStringLength, out short outLengthNeeded);
private const short SQL_HANDLE_ENV = 1, SQL_HANDLE_DBC = 2;
private const int SQL_ATTR_ODBC_VERSION = 200, SQL_OV_ODBC3 = 3;
private const short SQL_SUCCESS = 0, SQL_NEED_DATA = 99;
private const short DEFAULT_RESULT_SIZE = 1024;
private const string SQL_DRIVER_STR = "DRIVER=SQL Server";
public static string[] GetServers() {
string list = string.Empty;
IntPtr henv = IntPtr.Zero, hconn = IntPtr.Zero;
StringBuilder inStr = new StringBuilder(SQL_DRIVER_STR);
StringBuilder outStr = new StringBuilder(DEFAULT_RESULT_SIZE);
short inLen = (short)inStr.Length, lenNeeded = 0;
try {
if (SQLAllocHandle(SQL_HANDLE_ENV, henv, out henv) == SQL_SUCCESS &&
SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (IntPtr)SQL_OV_ODBC3, 0) == SQL_SUCCESS &&
SQLAllocHandle(SQL_HANDLE_DBC, henv, out hconn) == SQL_SUCCESS) {
short ret = SQLBrowseConnect(hconn, inStr, inLen, outStr, DEFAULT_RESULT_SIZE, out lenNeeded);
if (ret == SQL_NEED_DATA) {
if (DEFAULT_RESULT_SIZE < lenNeeded) {
outStr.Capacity = lenNeeded;
if (SQLBrowseConnect(hconn, inStr, inLen, outStr, lenNeeded, out lenNeeded) != SQL_NEED_DATA)
throw new ApplicationException("無法從 ODBC 驅動獲取 SQL Server 列表");
}
list = outStr.ToString();
int start = list.IndexOf("{") + 1;
int len = list.IndexOf("}") - start;
if (start > 0 && len > 0) list = list.Substring(start, len);
else list = string.Empty;
}
}
} catch { list = string.Empty; }
finally {
if (hconn != IntPtr.Zero) SQLFreeHandle(SQL_HANDLE_DBC, hconn);
if (henv != IntPtr.Zero) SQLFreeHandle(SQL_HANDLE_ENV, henv);
}
return list.Length > 0 ? list.Split(',') : null;
}
}
| 維度 | SQLDMO | ODBC API |
|---|---|---|
| 依賴 | SQLDMO COM 組件(需安裝客戶端工具) | 僅 odbc32.dll(系統自帶) |
| 版本支持 | ≤ SQL 2008 R2 | 所有版本(含 2012/2014/2016/2017/2019/2022) |
| 功能豐富度 | 極高(對象模型完整) | 僅枚舉服務器名 |
| 部署複雜度 | 需註冊 COM、位數匹配 | 零部署,P/Invoke 即用 |
| 推薦場景 | 舊系統維護、需操作對象屬性 | 新開發、僅需發現服務器、跨版本兼容 |
SQL Server 2005+ 官方托管 SDK,NuGet 安裝 Microsoft.SqlServer.SqlManagementObjects:
var server = new Server(".");
server.ConnectionContext.LoginSecure = true;
server.ConnectionContext.Connect();
foreach (Database db in server.Databases) Console.WriteLine(db.Name);
結論:新項目首選 SMO;舊項目維護用 SQLDMO;僅需枚舉實例名用 ODBC API 或 SqlDataSourceEnumerator.Instance.GetDataSources()(ADO.NET 內置)。