it编程 > 编程语言 > Asp.net

详解如何在C#中使用COM接口

8人参与 2025-03-05 Asp.net

在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如下所示

idesktopwallpaper

三、如果电脑上没有安装c++桌面开发负载,可以访问stevemk14ebr的gist来进行搜索

3、接口声明

有了com接口的guid后,我们需要对com接口进行声明

这里有几个方法可供参考:

一、通过c# + com接口为关键进行进行搜索

 例如搜索[c# idesktopwallpaper],然后在结果中查找,一般会有c#的接口声明,如果没找到相关结果,可以查看方法2

二、访问pinvoke.net搜索

我们打开pinvoke.net: the interop wiki!,搜索idesktopwallpaper

目前该网站已经停止维护,很大机率会搜索不出来。

三、访问msdn文档,通过数据类型映射,自行声明com接口

数据类型的映射可以参考下面的文章:

platform invoke data types | microsoft learn

这种方法虽然比较麻烦,但也算是最终解决方案了。

像我平常跟硬件交互比较多,这种映射也是家常便饭了。

需要注意的是,接口中涉及的类型也要进行声明。

例如void setposition(desktop_wallpaper_position position)参数里涉及了desktop_wallpaper_position,我们需要对这个desktop_wallpaper_position类型进行定义。

对于point或rect之类的,建议也是自己定义,不要使用c#内置类型,否则有可能会封送失败。

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类型,暂时不导入
     //void setslideshow(ishellitemarray items);
 
     //未引用ishellitemarray类型,暂时不导入
     //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、定义类

这个步骤和步骤3类似,但是不需要定义类的成员函数。这里的guid使用的是clsid_desktopwallpaper的guid

[comimport]
[guid("c2cf3110-460e-4fc1-b9d0-8a1c0c9cc4bd")]
 public class desktopwallpaper
 {
 
 }

5、使用

 idesktopwallpaper desktopwallpaper = (idesktopwallpaper)new desktopwallpaper();
 
 //调用成员函数
desktopwallpaper.xxxx();

方法二、自动生成(适用于.net6+版本)

自动生成主要是借助cswin32项目来实现这个功能,cswin32是一个源代码生成器,用于在 c# 项目中添加一组用户定义的 win32 p/invoke 方法和支持类型。

这种方法会比较简单方便,但是仅适用于.net core。.net framework无法使用。

另外还要求visual studio的版本至少是visual studio 2019 update 11 (16.11)

使用cswin32生成com接口的声明,在官方的文档中并未直接说明,我也是在一个issue中找到了实现方法。

实现步骤如下:

1、nuget导入microsoft.windows.cswin32包

2、在项目下,新建一个nativemethods.txt文件

3、在nativemethods.txt下输入需要导入的com接口

例如我们想使用idesktopwallpaper接口,就在nativemethods.txt下输入

 idesktopwallpaper
 desktopwallpaper

注意:

1、两个类型都需要写,如果只写了idesktopwallpaper,就无法实例化接口。我一开始就是卡在这里。

2、需要生成接口的类型都可以写在nativemethods.txt里,每个类型单独一行。

4、通过代码生成器生成的类型在哪

对于自动生成的类型,命名空间都不一样,但是都是在windows.win32命名空间下。

在visual studio中,输入windows.win32,自己定位所需要类型所在的命名空间即可。

例如idesktopwallpaper所在的命名空间是:windows.win32.ui.shell

也可以通过ctrl+t,输入类型名称进行查找 

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 // 验证平台兼容性
                 desktopwallpaper.getwallpaper(szmonitorid, &pwstr);
 #pragma warning restore ca1416 // 验证平台兼容性
 
                 messagebox.show(pwstr.tostring());
             }

说明:cswin32项目在生成lpwstr/pwstr类型时没有使用c#的类型进行映射,例如只读字符串的使用string,需要写入字符串的使用分配空间后的stringbuilder。

所以不得不使用unsafe关键字,并使用指针。这种方法并不太友好 。

以上就是详解如何在c#中使用com接口的详细内容,更多关于c#使用com接口的资料请关注代码网其它相关文章!

(0)
打赏 微信扫一扫 微信扫一扫

您想发表意见!!点此发布评论

推荐阅读

C#实现日期操作类DateTime的方法示例

03-05

C# 类库打包dll文件的操作流程

03-05

C#实现一个相当全面的数据转换工具类

03-06

基于C#实现语音合成播报器

03-06

C# winform操作CSV格式文件

03-06

C#加锁防止并发的几种方法详解

03-06

猜你喜欢

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论