System.Windows.Form 底下的 Dialog(對話框)很實用。程式能透過 Dialog 輔助使用者正確輸入 Y/N、檔案路徑甚至是字型、顏色。
如果有現成的輸入資料庫連線的 Dialog 就好了。我發現 Windows 對 .udl 檔有很親切的 UI 介面,會面面俱到地輔助連線設定,串一下就有現成的 Dialog 了
當手邊的 Windows 沒有裝 SSMS 等要額外安裝的工具又要測試連線時,有個超好用的小撇步。
只要右鍵新增文字檔再把 .txt 副檔名改成 .udl,再把檔案雙擊開啟就有現成的連線對話框。
功能完整,按 OK 之後就會存入 OLE DB 連線字串,可以用記筆本打開,如果是連 MSSQL 把頭尾去掉就能直接放到 SqlConnection 了。
最近想到這特性其實能直接變成 .NET 程式的對話框,關鍵要能抓到編輯結束使用者按下 OK 的事件。以下是實現這個想法的範例碼
void Main()
{
var connStr = AskConnectionByUdl();
if (connStr is null)
{
Console.WriteLine("null 可能是使用者沒按確定或輸入內容無法解析.");
}
else
{
Console.WriteLine($"成功透到 .udl GUI 取得連線字串:{connStr}");
}
}
// Define other methods and classes here
/// <summary>
/// 利用 Windows 預設的 .udl 開啟方式來輸入連線資訊
/// </summary>
string AskConnectionByUdl()
{
var udl = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.udl");
udl.Dump("產生 .udl 在 temp 資料夾");
var connStr = (string)null;
try
{
var file = File.Open(udl, FileMode.OpenOrCreate);
file.Dispose();
// Windows 預設以 Ole DB Core Services 開啟 .udl
var pro = Process.Start(udl);
pro.WaitForExit();
var udlText = File.ReadAllText(udl);
Console.WriteLine($"使用者連線編輯結束.取得連線資訊(OLE):{udlText}");
connStr = ConvertOle2Sql(udlText);
return connStr;
}
finally
{
File.Delete(udl);
}
}
/// <summary>
/// 只用簡單的字串處理來轉成 ADO SQL 連線字串
/// </summary>
string ConvertOle2Sql(string oleTxt)
{
var oleStr = oleTxt.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries).LastOrDefault();
if (string.IsNullOrEmpty(oleStr))
{
return null;
}
// modify config
var oleConn = oleStr;
// to sql connection
var connStr = oleConn.Split(new[] { ';' }, 2)[1];
var last = connStr.IndexOf(";Initial File");
if (last != -1) connStr = connStr.Substring(0, last);
connStr = connStr.Replace(@"User ID="""";", "");
var conb = new SqlConnectionStringBuilder(connStr);
return conb.ToString();
}
只要用 Process 開啟 .udl 檔,再用 WaitForExit() 等待使用者結束編輯即可,剩下的就是讀取檔案做字串處理。
這段程式碼已經能應付大部分情境了。還有一些細節,加入之後會變很長。
例如上面這段程式只能跑在 .NET Framework 在 .NET Core 會跳錯,因為 Process 在 Core 的預設值不一樣 UseShellExecute 是 false,要在 Core 執行可以改用
var pro = Process.Start(new ProcessStartInfo() {UseShellExecute=true, FileName=udl});
UseShellExecute 開啟,會讓系統執行該副檔名預設的開啟方式,但如果不幸使用者改了 .udl 的預設變成記事本,那我們原本以為會開啟對話框,就會變成開啟記事本。
對這種狀況,要指定用 OLE DB Core Services 開啟,對應地副檔名就不用限定 .udl 了。
var args = @$"""C:\Program Files\Common Files\System\Ole DB\oledb32.dll"",OpenDSLFile {udl}";
var pro = pro = Process.Start("rundll32.exe", args);
上面這段 Code 只能用在 Windows,話雖如此我也並不知道 Linux 或 Mac 是否預裝有支援編輯 .udl 的應用。
範例只假設了 MSSQL 的情境,而且對其它類型的連線沒有防呆,如果要防呆要檢查 OLE DB 字串的 Provider 屬性,目前已知的 MSSQL 的 Provider 分別是 MSOLEDBSQL
、SQLOLEDB
、SQLNCLI
作開頭(如果發現有缺歡迎留言告知)
其實我還想過為對話框附加 Always on top 的功能,因為 .udl 的視窗有點特殊,它不會顯示在工作列。一般拿到 Process.MainWindowHandle 輸入到控制視窗的 Win32 API 就可以了,但 rundll32.exe 本身並沒有 MainWindowHandle,到現在到還不能很好地實現,不過這功能最多就是錦上添花而已。
以上就是偷個懶不用刻連線資訊輸入畫面的小撇步。