和其他語言一樣,C#實現檔案關聯同樣需要直接操作註冊表,即按規則分別設定副檔名,文件類型說明,易記名稱,表徵圖,調用方法等索引值即可,網上隨便查查就可以寫出以下的代碼。
using Microsoft.Win32;
RegistryKey key = Registry.ClassesRoot.OpenSubKey(".jb");
if (key == null)
{
key = Registry.ClassesRoot.CreateSubKey(".jb");
key.SetValue("", "Jeebook.Reader.jb");
key.SetValue("Content Type", "application/jb");
key = Registry.ClassesRoot.CreateSubKey("Jeebook.Reader.jb");
key.SetValue("", "Jeebook Document");
RegistryKey keySub = key.CreateSubKey("DefaultIcon");
keySub.SetValue("", System.Windows.Forms.Application.StartupPath + "Jeebook.ico");
keySub = key.CreateSubKey("shell//open//command");
keySub.SetValue("", "/"" + System.Windows.Forms.Application.ExecutablePath + "/" /"%1/"");
}
相對來說,C#實現比較麻煩的是表徵圖路徑,一般檔案類型註冊的都是執行檔案的資源,格式如下:
格式:, // 資源ID為正數,表示資源的索引號,否則為資源ID
在C++中很容易擷取資源ID,但C#中還沒搞清楚如何取道資源的ID,所以索性在程式執行目錄下附帶一個表徵圖檔案用於註冊,這樣倒也方便隨時修改:)
此外,就是如何驗證表徵圖是否設定正確。現在的系統超愛緩衝,除非LOG OFF層級的操作,否則手工修改註冊表很難馬上響應,當然通過程式調用應該重新整理系統狀態,這個下次有時間再研究吧
如果只是用於XP以下的程式,以上的代碼就已經足夠了。可惜的是,Vista以後引入了UAC,上面的代碼在UAC下會彈出異常,這肯定不是我們希望的。
一種解決方案是通過建立一個Mainifest檔案,添加以下指令碼:
這樣程式表徵圖上會出現一個小盾牌,表示該程式需要在管理員模式下運行,每次運行都會自動彈出UAC的驗證視窗。但這個對某些只是需要書寫一次註冊表的程式來說,每次都彈出提示是無法忍受的,那麼如何能夠通過代碼彈出UAC驗證視窗呢?
Google的結果,貌似沒有在運行中觸發提示並將進程改變為管理員模式的辦法,不過只要在執行進程時將Verb設定為runas就可以自動觸發UAC驗證,使被調用的程式在管理員模式下運行。那麼,只要在程式中重新啟動自己就可以達到觸發UAC驗證視窗的目的,代碼如下:
System.Diagnostics.ProcessStartInfo start = new System.Diagnostics.ProcessStartInfo();
System.Diagnostics.Process p = new System.Diagnostics.Process();
start.WorkingDirectory = System.Windows.Forms.Application.StartupPath;
start.Verb = "runas";
start.FileName = System.Windows.Forms.Application.ExecutablePath;
System.Diagnostics.Process.Start(start);
當然,如果你將上面的代碼直接放入你的FormLoad中,那將是場災難,因為你的程式會不斷的啟動自己直到把你的機器資源耗光為止。所以我們還需要有能夠判斷是否已經進入管理員模式的代碼,如下:
WindowsIdentity wi = WindowsIdentity.GetCurrent();
WindowsPrincipal wp = new WindowsPrincipal(wi);
if (!wp.IsInRole(WindowsBuiltInRole.Administrator))
wi代表的是目前使用者,WindowsBuiltInRole.Administrator是管理員的標識符(比較奇怪的是VB好像有自己特殊的名字空間來實現以上的功能,不知為什麼,當然我們用標準的方法判斷也沒什麼不好)
由此將以上所有的代碼整合起來,得到以下的結果:
if ( null != Registry.ClassesRoot.OpenSubKey(".jb") )
return;
WindowsIdentity wi = WindowsIdentity.GetCurrent();
WindowsPrincipal wp = new WindowsPrincipal(wi);
if (!wp.IsInRole(WindowsBuiltInRole.Administrator))
{
System.Diagnostics.ProcessStartInfo start = new
System.Diagnostics.ProcessStartInfo();
System.Diagnostics.Process p = new System.Diagnostics.Process();
start.WorkingDirectory = System.Windows.Forms.Application.StartupPath;
start.Verb = "runas";
start.FileName = System.Windows.Forms.Application.ExecutablePath;
System.Diagnostics.Process.Start(start);
Application.Exit();
return;
}
RegistryKey key = Registry.ClassesRoot.OpenSubKey(".jb");
if (key == null)
{
key = Registry.ClassesRoot.CreateSubKey(".jb");
key.SetValue("", "Jeebook.Reader.jb");
key.SetValue("Content Type", "application/jb");
key = Registry.ClassesRoot.CreateSubKey("Jeebook.Reader.jb");
key.SetValue("", "Jeebook Document");
RegistryKey keySub = key.CreateSubKey("DefaultIcon");
keySub.SetValue("", System.Windows.Forms.Application.StartupPath + "Jeebook.ico");
keySub = key.CreateSubKey("shell//open//command");
keySub.SetValue("", "/"" + System.Windows.Forms.Application.ExecutablePath + "/" /"%1/"");
}
檔案關聯是個很常用很簡單的功能,但真要做的好,還得費點功夫啊:)