国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

.net比較完美的動態注冊com組件

2019-11-17 02:20:58
字體:
來源:轉載
供稿:網友

.net比較完美的動態注冊com組件

.net中經常需要使用com組件,怎么樣注冊com組件呢?

一般想到的當然是直接通過系統cmd 調用regsvr32注冊程序去注冊,如下:

regsvr32 name.dll

在.net中可以直接執行cmd命令如下:

System.Diagnostics.PRocess.Start("regsvr32.exe","name.dll");

問題來了,那怎么去檢查一個dll已經注冊了呢?不能每次都注冊吧!我們知道每一個com組件都有一個clsid,如果已經注冊了,那么在系統注冊表里面會有注冊信息的。 csharp代碼如下:

private static bool IsExistRegister(Guid guid){RegistryKey rkTest = Registry.ClassesRoot.OpenSubKey(String.Format("CLSID//{{{0}}}//InprocServer32", guid.ToString()));if (rkTest != null){var val = rkTest.GetValue("");//獲取注冊表中注冊的dll路徑if (val != null){return System.IO.File.Exists(val.ToString());}}return false;}

似乎通過上面的代碼已經解決了所有問題,但是我個人并不滿足上面的方案,原因如下:

  1. 不喜歡直接在.net中調用cmd命令
  2. 當檢查是否注冊時,必須預先知道com的clsid。

那么有么有方法解決上面2個問題呢?答案當然是肯定的! 通過查詢資料得知:regsvr32 name.dll 實際上就是調用name.dll中的一個方法:DllRegisterServer。在.net中我們可以通過pinvoke直接調用dll這個方法就可以了,代碼如下:

static class NameDll{[DllImport("name.dll")]public static extern int DllRegisterServer();[DllImport("name.dll")]public static extern int DllUnregisterServer();}

然后在.net中直接通過NameDll.DllRegisterServer();即可完成注冊。 這個辦法不需要在.net中調用cmd命令,但是有個缺點。每一個dll都需要這么定義下。因為[DllImport("name.dll")]這個路徑不能動態給。所以也不是很好。其實在.net中有可以動態加載dll并根據需要調用dll中方法的代碼如下:

public class Win32DllWrap : IDisposable{[DllImport("kernel32.dll")]private extern static IntPtr LoadLibrary(String path);[DllImport("kernel32.dll")]private extern static IntPtr GetProcAddress(IntPtr lib, String funcName);[DllImport("kernel32.dll")]private extern static bool FreeLibrary(IntPtr lib);private IntPtr hLib;public Win32DllWrap(String DLLPath){hLib = LoadLibrary(DLLPath);}/// <summary>/// 根據函數名獲取dll中的函數指針,并轉化為指定的TDelegate類型/// </summary>/// <typeparam name="TDelegate"></typeparam>/// <param name="name"></param>/// <returns></returns>public TDelegate GetFunc<TDelegate>(String name) where TDelegate : class{IntPtr api = GetProcAddress(hLib, name);return Marshal.GetDelegateForFunctionPointer(api, typeof(TDelegate)) as TDelegate;}public void Dispose(){FreeLibrary(hLib);}}/*using(var dll = new Win32DllWrap(path)){     var method = dll.GetFunc<Action>("DllRegisterServer");//根據名字獲取方法,并返回對于的委托     method();//完成注冊}*/

這個方法避免了每一個com組件要定義個類的弊端。而且完全可以根據com路徑動態注冊。但是大家別忘了,上面還有一個問題沒解決。

那就是在檢查com是否注冊時,怎么動態得知指定路徑com的clsid。 廢話也不多說。代碼如下

private static List<Guid> GetClsids(string path){if (!System.IO.File.Exists(path)){throw new Exception(path + "文件不存在");}List<Guid> list = new List<Guid>();ITypeLib lib;IntPtr attrPtr;ITypeInfo info;LoadTypeLib(path, out lib);if (lib == null){throw new Exception(path + "不是com組件");}var n = lib.GetTypeInfoCount();for (int i = 0; i < n; i++){lib.GetTypeInfo(i, out info);if (info != null){info.GetTypeAttr(out attrPtr);if (attrPtr != null){var v = (System.Runtime.InteropServices.ComTypes.TYPEATTR)Marshal.PtrToStructure(attrPtr, typeof(System.Runtime.InteropServices.ComTypes.TYPEATTR));if (v.typekind == System.Runtime.InteropServices.ComTypes.TYPEKIND.TKIND_COCLASS){list.Add(v.guid);}info.ReleaseTypeAttr(attrPtr);}}}return list;}

上面這個方法可以獲取給定路徑的dll中的clsid列表。 老實講:這個方法我是真的費盡心力,網上幾乎沒.net的資料。至此所有問題都已經解決。我們完全可以根據指定路徑注冊動態注冊com組件,并能判斷是否已經注冊。我簡單封裝一下代碼:

/// <summary>/// Com組件注冊類/// </summary>public class ComRegHelp{   private delegate void comDelegate();/// <summary>/// 注冊指定路徑的dll,如果已經注冊,就不注冊/// </summary>/// <param name="dllPath"></param>public static void Registe(string dllPath){if (!IsRegistered(dllPath)){using (var dll = new Win32DllWrap(dllPath)){dll.GetFunc<comDelegate>("DllRegisterServer")();}}}/// <summary>/// 取消注冊指定路徑的dll/// </summary>/// <param name="dllPath"></param>public static void UnRegiste(string dllPath){using (var dll = new Win32DllWrap(dllPath)){dll.GetFunc<comDelegate>("DllUnregisterServer")();}}private static List<Guid> GetClsids(string path){if (!System.IO.File.Exists(path)){throw new Exception(path + "文件不存在");}List<Guid> list = new List<Guid>();ITypeLib lib;IntPtr attrPtr;ITypeInfo info;LoadTypeLib(path, out lib);if (lib == null){throw new Exception(path + "不是com組件");}var n = lib.GetTypeInfoCount();for (int i = 0; i < n; i++){lib.GetTypeInfo(i, out info);if (info != null){info.GetTypeAttr(out attrPtr);if (attrPtr != null){var v = (System.Runtime.InteropServices.ComTypes.TYPEATTR)Marshal.PtrToStructure(attrPtr, typeof(System.Runtime.InteropServices.ComTypes.TYPEATTR));if (v.typekind == System.Runtime.InteropServices.ComTypes.TYPEKIND.TKIND_COCLASS){list.Add(v.guid);}info.ReleaseTypeAttr(attrPtr);}}}return list;}[DllImport("oleaut32.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]static extern int LoadTypeLib(string fileName, out ITypeLib typeLib);/// <summary>/// 判斷指定路徑dll是否已經注冊/// </summary>/// <param name="path"></param>/// <returns></returns>public static bool IsRegistered(string path){var guids = GetClsids(path);foreach (var item in guids){if (IsExistRegister(item)){return true;}}return false;}private static bool IsExistRegister(Guid guid){RegistryKey rkTest = Registry.ClassesRoot.OpenSubKey(String.Format("CLSID//{{{0}}}//InprocServer32", guid.ToString()));if (rkTest != null){var val = rkTest.GetValue("");if (val != null){return System.IO.File.Exists(val.ToString());}}return false;}}

完畢,希望對大家有用!


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 博野县| 武夷山市| 额尔古纳市| 任丘市| 嘉禾县| 法库县| 凌云县| 尚志市| 葫芦岛市| 肇庆市| 纳雍县| 宁强县| 波密县| 运城市| 重庆市| 铜山县| 峨眉山市| 张家口市| 雅安市| 常山县| 腾冲县| 东城区| 砚山县| 嘉黎县| 上林县| 灵台县| 那曲县| 樟树市| 资源县| 明溪县| 同德县| 富川| 崇义县| 渝中区| 贵定县| 体育| 琼海市| 青州市| 马鞍山市| 色达县| 丰顺县|