詳解如何在C#中使用COM接口
在C++中,可以使用CoCreateInstance函數(shù)來創(chuàng)建COM接口的實(shí)例。
以下教程可以幫助你方便的在C#中實(shí)現(xiàn)同樣的功能。
方法一、手動(dòng)生成(適用于所有.NET版本)
1、確定要使用的COM接口
Windows中很多功能都是通過COM實(shí)現(xiàn)的,有時(shí)候我們想實(shí)現(xiàn)一些系統(tǒng)功能,但是又沒有直接的Win32 API代調(diào)用,就可以尋找COM接口替代。
至于使用哪個(gè)COM接口,這個(gè)可以通過搜索引擎。
例如,我想設(shè)置桌面壁紙,可以通過IDesktopWallpaper接口來實(shí)現(xiàn)。
2、查找COM接口的GUID
這里提供了幾種方案
一、通過搜索引擎,常用的COM接口,可以通過搜索引擎直接搜索到GUID
二、對(duì)于不常用的COM接口,可能搜索引擎不能搜索到對(duì)應(yīng)的GUID,我們可以創(chuàng)建一個(gè)Win32工程(需要Visual Studio安裝C++桌面開發(fā)),然后輸入CLSID_接口名稱,再按F12就可以看到GUID。
例如:CLSID_DesktopWallpaper,按F12如下所示
IDesktopWallpaper
三、如果電腦上沒有安裝C++桌面開發(fā)負(fù)載,可以訪問stevemk14ebr的gist來進(jìn)行搜索
3、接口聲明
有了COM接口的GUID后,我們需要對(duì)COM接口進(jìn)行聲明
這里有幾個(gè)方法可供參考:
一、通過C# + COM接口為關(guān)鍵進(jìn)行進(jìn)行搜索
例如搜索[C# IDesktopWallpaper],然后在結(jié)果中查找,一般會(huì)有C#的接口聲明,如果沒找到相關(guān)結(jié)果,可以查看方法2
二、訪問pinvoke.net搜索
我們打開pinvoke.net: the interop wiki!,搜索IDesktopWallpaper
目前該網(wǎng)站已經(jīng)停止維護(hù),很大機(jī)率會(huì)搜索不出來。
三、訪問MSDN文檔,通過數(shù)據(jù)類型映射,自行聲明COM接口
數(shù)據(jù)類型的映射可以參考下面的文章:
Platform Invoke Data Types | Microsoft Learn
這種方法雖然比較麻煩,但也算是最終解決方案了。
像我平常跟硬件交互比較多,這種映射也是家常便飯了。
需要注意的是,接口中涉及的類型也要進(jìn)行聲明。
例如void SetPosition(DESKTOP_WALLPAPER_POSITION position)參數(shù)里涉及了DESKTOP_WALLPAPER_POSITION,我們需要對(duì)這個(gè)DESKTOP_WALLPAPER_POSITION類型進(jìn)行定義。
對(duì)于POINT或RECT之類的,建議也是自己定義,不要使用C#內(nèi)置類型,否則有可能會(huì)封送失敗。
IDesktopWallpaper在C#中聲明如下:
[ComVisible(true)] public enum DESKTOP_SLIDESHOW_DIRECTION { DSD_FORWARD = 0, DSD_BACKWARD = 1 } public struct RECT { public int left; public int top; public int right; public int bottom; } [ComVisible(true)] public enum DESKTOP_WALLPAPER_POSITION { DWPOS_CENTER = 0, DWPOS_TILE = 1, DWPOS_STRETCH = 2, DWPOS_FIT = 3, DWPOS_FILL = 4, DWPOS_SPAN = 5 } [ComVisible(true)] [Flags] public enum DESKTOP_SLIDESHOW_STATE { DSS_ENABLED = 1, DSS_SLIDESHOW = 2, DSS_DISABLED_BY_REMOTE_SESSION = 4 } [ComImport] [Guid("B92B56A9-8B55-4E14-9A89-0199BBB6F93B")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IDesktopWallpaper { void SetWallpaper([MarshalAs(UnmanagedType.LPWStr)] string monitorID, [MarshalAs(UnmanagedType.LPWStr)] string wallpaper); [return: MarshalAs(UnmanagedType.LPWStr)] StringBuilder GetWallpaper([MarshalAs(UnmanagedType.LPWStr)] string monitorID); [return: MarshalAs(UnmanagedType.LPWStr)] StringBuilder GetMonitorDevicePathAt(uint monitorIndex); [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] uint GetMonitorDevicePathCount(); RECT GetMonitorRECT([MarshalAs(UnmanagedType.LPWStr)] string monitorID); void SetBackgroundColor(uint color); uint GetBackgroundColor(); void SetPosition([MarshalAs(UnmanagedType.I4)] DESKTOP_WALLPAPER_POSITION position); [return: MarshalAs(UnmanagedType.I4)] DESKTOP_WALLPAPER_POSITION GetPosition(); //未引入IShellItemArray類型,暫時(shí)不導(dǎo)入 //void SetSlideshow(IShellItemArray items); //未引用IShellItemArray類型,暫時(shí)不導(dǎo)入 //IShellItemArray GetSlideshow(); //IntPtr GetSlideshow(); void SetSlideshowOptions(uint options, uint slideshowTick); void GetSlideshowOptions(out uint options, out uint slideshowTick); void AdvanceSlideshow([MarshalAs(UnmanagedType.LPWStr)] string monitorID, [MarshalAs(UnmanagedType.I4)] DESKTOP_SLIDESHOW_DIRECTION direction); DESKTOP_SLIDESHOW_STATE GetStatus(); void Enable([MarshalAs(UnmanagedType.Bool)] bool enable); }
4、定義類
這個(gè)步驟和步驟3類似,但是不需要定義類的成員函數(shù)。這里的GUID使用的是CLSID_DesktopWallpaper的GUID
[ComImport] [Guid("C2CF3110-460E-4FC1-B9D0-8A1C0C9CC4BD")] public class DesktopWallpaper { }
5、使用
IDesktopWallpaper desktopWallpaper = (IDesktopWallpaper)new DesktopWallpaper(); //調(diào)用成員函數(shù) desktopWallpaper.xxxx();
方法二、自動(dòng)生成(適用于.NET6+版本)
自動(dòng)生成主要是借助Cswin32項(xiàng)目來實(shí)現(xiàn)這個(gè)功能,CsWin32是一個(gè)源代碼生成器,用于在 C# 項(xiàng)目中添加一組用戶定義的 Win32 P/Invoke 方法和支持類型。
這種方法會(huì)比較簡單方便,但是僅適用于.NET Core。.Net Framework無法使用。
另外還要求Visual Studio的版本至少是Visual Studio 2019 Update 11 (16.11)。
使用CsWin32生成COM接口的聲明,在官方的文檔中并未直接說明,我也是在一個(gè)issue中找到了實(shí)現(xiàn)方法。
實(shí)現(xiàn)步驟如下:
1、nuget導(dǎo)入Microsoft.Windows.CsWin32包
2、在項(xiàng)目下,新建一個(gè)NativeMethods.txt文件
3、在NativeMethods.txt下輸入需要導(dǎo)入的COM接口
例如我們想使用IDesktopWallpaper接口,就在NativeMethods.txt下輸入
IDesktopWallpaper DesktopWallpaper
注意:
1、兩個(gè)類型都需要寫,如果只寫了IDesktopWallpaper,就無法實(shí)例化接口。我一開始就是卡在這里。
2、需要生成接口的類型都可以寫在NativeMethods.txt里,每個(gè)類型單獨(dú)一行。
4、通過代碼生成器生成的類型在哪
對(duì)于自動(dòng)生成的類型,命名空間都不一樣,但是都是在Windows.Win32命名空間下。
在Visual Studio中,輸入Windows.Win32,自己定位所需要類型所在的命名空間即可。
例如IDesktopWallpaper所在的命名空間是:Windows.Win32.UI.Shell
也可以通過Ctrl+T,輸入類型名稱進(jìn)行查找
5、使用
Windows.Win32.UI.Shell.IDesktopWallpaper desktopWallpaper = (Windows.Win32.UI.Shell.IDesktopWallpaper)new Windows.Win32.UI.Shell.DesktopWallpaper(); Windows.Win32.Foundation.PWSTR pWSTR = new Windows.Win32.Foundation.PWSTR(); unsafe { char* p = stackalloc char[1]; p[0] = '0'; Windows.Win32.Foundation.PWSTR szMonitorId = new Windows.Win32.Foundation.PWSTR(p); #pragma warning disable CA1416 // 驗(yàn)證平臺(tái)兼容性 desktopWallpaper.GetWallpaper(szMonitorId, &pWSTR); #pragma warning restore CA1416 // 驗(yàn)證平臺(tái)兼容性 MessageBox.Show(pWSTR.ToString()); }
說明:CsWin32項(xiàng)目在生成LPWSTR/PWSTR類型時(shí)沒有使用C#的類型進(jìn)行映射,例如只讀字符串的使用string,需要寫入字符串的使用分配空間后的StringBuilder。
所以不得不使用unsafe關(guān)鍵字,并使用指針。這種方法并不太友好 。
以上就是詳解如何在C#中使用COM接口的詳細(xì)內(nèi)容,更多關(guān)于C#使用COM接口的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
字符串和十六進(jìn)制之間的轉(zhuǎn)換方法實(shí)例
這篇文章介紹了字符串和十六進(jìn)制之間的轉(zhuǎn)換方法實(shí)例,有需要的朋友可以參考一下2013-11-11Unity實(shí)現(xiàn)游戲卡牌滾動(dòng)效果
這篇文章主要為大家詳細(xì)介紹了Unity實(shí)現(xiàn)游戲卡牌滾動(dòng)效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-02-02ItemsControl 數(shù)據(jù)綁定的兩種方式
這篇文章主要介紹了ItemsControl 數(shù)據(jù)綁定的兩種方式,幫助大家更好的理解和學(xué)習(xí)使用c#,感興趣的朋友可以了解下2021-03-03