在C++中,可以使用CoCreateInstance函数来创建COM接口的实例。
以下教程可以帮助你方便的在C#中实现同样的功能。
方法一、手动生成(适用于所有.NET版本)
1、确定要使用的COM接口
Windows中很多功能都是通过COM实现的,有时候我们想实现一些系统功能,但是又没有直接的Win32 API代调用,就可以寻找COM接口替代。
至于使用哪个COM接口,这个可以通过搜索引擎。
例如,我想设置桌面壁纸,就可以通过IDesktopWallpaper接口来实现。
2、查找COM接口的GUID
这里提供了几种方案
一、通过搜索引擎,常用的COM接口,可以通过搜索引擎直接搜索到GUID
二、对于不常用的COM接口,可能搜索引擎不能搜索到对应的GUID,我们可以创建一个Win32工程(需要Visual Studio安装C++桌面开发),然后输入CLSID_接口名称,再按F12就可以看到GUID。
例如:CLSID_DesktopWallpaper,按F12如下所示
三、如果电脑上没有安装C++桌面开发负载,可以访问stevemk14ebr的gist来进行搜索
3、接口声明
有了COM接口的GUID后,我们需要对COM接口进行声明
这里有几个方法可供参考:
一、通过C# + COM接口为关键进行进行搜索
例如搜索[C# IDesktopWallpaper],然后在结果中查找,一般会有C#的接口声明,如果没找到相关结果,可以查看方法2
二、访问pinvoke.net搜索
我们打开https://www.pinvoke.net/,搜索IDesktopWallpaper
目前该网站已经停止维护,所以基本上搜索不出来。
三、访问MSDN文档,通过数据类型映射,自行声明COM接口
可以参考下面的文章:
https://learn.microsoft.com/en-us/previous-versions/dotnet/netframework-4.0/ac7ay120(v=vs.100)?redirectedfrom=MSDN
这种方法虽然比较麻烦,但也算是最终解决方案了。
需要注意的是,接口中涉及的类型也需要进行声明。
例如IDesktopWallpaper在C#中声明如下:
1 using System; 2 using System.Runtime.CompilerServices; 3 using System.Runtime.InteropServices; 4 using System.Text; 5 6 namespace IDesktopWallpaperWrapper.Win32 7 { 8 /// <summary> 9 /// The direction that the slideshow should advance. 10 /// </summary> 11 [ComVisible(true)] 12 public enum DESKTOP_SLIDESHOW_DIRECTION 13 { 14 /// <summary> 15 /// Advance the slideshow forward. 16 /// </summary> 17 DSD_FORWARD = 0, 18 /// <summary> 19 /// Advance the slideshow backward. 20 /// </summary> 21 DSD_BACKWARD = 1 22 } 23 24 25 26 /// <summary> 27 /// Specifies how the desktop wallpaper should be displayed. 28 /// </summary> 29 [ComVisible(true)] 30 public enum DESKTOP_WALLPAPER_POSITION 31 { 32 /// <summary> 33 /// Center the image; do not stretch. 34 /// </summary> 35 DWPOS_CENTER = 0, 36 /// <summary> 37 /// Tile the image across all monitors. 38 /// </summary> 39 DWPOS_TILE = 1, 40 /// <summary> 41 /// Stretch the image to exactly fit on the monitor. 42 /// </summary> 43 DWPOS_STRETCH = 2, 44 /// <summary> 45 /// Stretch the image to exactly the height or width of the monitor without changing its aspect ratio or cropping the image. 46 /// This can result in colored letterbox bars on either side or on above and below of the image. 47 /// </summary> 48 DWPOS_FIT = 3, 49 /// <summary> 50 /// Stretch the image to fill the screen, cropping the image as necessary to avoid letterbox bars. 51 /// </summary> 52 DWPOS_FILL = 4, 53 /// <summary> 54 /// Spans a single image across all monitors attached to the system. 55 /// </summary> 56 DWPOS_SPAN = 5 57 } 58 59 60 61 [ComVisible(true)] 62 [Flags] 63 public enum DESKTOP_SLIDESHOW_STATE 64 { 65 /// <summary> 66 /// Slideshows are enabled. 67 /// </summary> 68 DSS_ENABLED = 1, 69 /// <summary> 70 /// A slideshow is currently configured. 71 /// </summary> 72 DSS_SLIDESHOW = 2, 73 /// <summary> 74 /// A remote session has temporarily disabled the slideshow. 75 /// </summary> 76 DSS_DISABLED_BY_REMOTE_SESSION = 4 77 } 78 79 80 81 /// <summary> 82 /// COM interface providing methods for managing the desktop wallpaper. 83 /// Instantiate this COM interface with DesktopWallpaper wrapper class instead. 84 /// </summary> 85 /// <remarks> 86 /// Windows 8 or later is required in order to access this interface. 87 /// </remarks> 88 [ComImport] 89 [Guid("b92b56a9-8b55-4e14-9a89-0199bbb6f93b")] 90 [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 91 public interface IDesktopWallpaper 92 { 93 // As with any COM import, method ordering is crucial to the functioning of the interface. 94 // The code ordering below must be maintained, else an AccessViolationException can be thrown. 95 96 //[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] 97 void SetWallpaper([MarshalAs(UnmanagedType.LPWStr)] string monitorID, [MarshalAs(UnmanagedType.LPWStr)] string wallpaper); 98 99 //[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] 100 [return: MarshalAs(UnmanagedType.LPWStr)] 101 StringBuilder GetWallpaper([MarshalAs(UnmanagedType.LPWStr)] string monitorID); 102 103 //[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] 104 [return: MarshalAs(UnmanagedType.LPWStr)] 105 StringBuilder GetMonitorDevicePathAt(uint monitorIndex); 106 107 [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] 108 uint GetMonitorDevicePathCount(); 109 110 //[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] 111 RECT GetMonitorRECT([MarshalAs(UnmanagedType.LPWStr)] string monitorID); 112 113 //[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] 114 void SetBackgroundColor(uint color); 115 116 //[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] 117 uint GetBackgroundColor(); 118 119 //[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] 120 void SetPosition([MarshalAs(UnmanagedType.I4)] DESKTOP_WALLPAPER_POSITION position); 121 122 //[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] 123 [return: MarshalAs(UnmanagedType.I4)] 124 DESKTOP_WALLPAPER_POSITION GetPosition(); 125 126 //[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] 127 void SetSlideshow(IShellItemArray items); 128 //void SetSlideshow(IntPtr items); 129 130 //[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] 131 IShellItemArray GetSlideshow(); 132 //IntPtr GetSlideshow(); 133 134 //[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] 135 void SetSlideshowOptions(uint options, uint slideshowTick); 136 137 //[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] 138 void GetSlideshowOptions(out uint options, out uint slideshowTick); 139 140 // NOT IMPLEMENTED BY COCLASS 141 //[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] 142 void AdvanceSlideshow([MarshalAs(UnmanagedType.LPWStr)] string monitorID, [MarshalAs(UnmanagedType.I4)] DESKTOP_SLIDESHOW_DIRECTION direction); 143 144 //[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] 145 DESKTOP_SLIDESHOW_STATE GetStatus(); 146 147 //[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] 148 void Enable([MarshalAs(UnmanagedType.Bool)] bool enable); 149 } 150 }
4、定义类
这个步骤和步骤3类似,但是不需要定义类的成员函数。
1 [ComImport] 2 [Guid("b92b56a9-8b55-4e14-9a89-0199bbb6f93b")] 3 4 public class DesktopWallpaper 5 { 6 7 }
5、使用
1 IDesktopWallpaper desktopWallpaper = (IDesktopWallpaper)new DesktopWallpaper(); 2 3 //调用成员函数 4 desktopWallpaper.xxxx();
方法二、自动生成(适用于.NET6+版本)
标签:Runtime,MethodImpl,C#,MethodImplOptions,接口,InternalCall,COM,MethodCodeType From: https://www.cnblogs.com/zhaotianff/p/18657903