C#创建COM组件

时间:2021-07-01 03:15:34

以下所讲述的过程,在VS2008测试通过。

 

1、 首先创建一个c#的类库项目。

2、 将AssemblyInfo.cs文件中的[assembly: ComVisible(false)]改为[assembly: ComVisible(true)],或者在项目属性-》应用程序-》程序集信息...-》勾选“使程序集COM可见”复选框。

3、 在项目属性-》”生成”中构选上”为COM互操作注册”复选框。

 

请记住:想要把C#对象当作COM对象需要以下几点...

  • class必须是public的
  • 属性,方法和事件必须是public
  • 属性和方法必须在Interface里面定义
  • 事件必须在事件的接口中

未在接口中定义的成员,而在实现里面是public的成员,对COM是不可见的,但是对其他的.NET程序是可见的.为了把属性和方法暴露给 COM,你必须在接口中定义他们,并且把他们用DispId属性标记,在class里面实现.在接口里面定义的成员只是为了使用 vtable(虚函数表).要想暴露事件,你也必须把成员定义在事件接口里面并且标记DispId属性.类不需要实现此接口.类可以实现接口 (一个类可以实现多个接口,只有第一个接口才是默认的接口.).暴露给COM的那些属性方法其实就在类的实现里面.他们必须被标记为public,而且要符合接口里面的定义.Also, declare the events raised by the class here. They must be marked public and must match the declarations in the events interface. (这两句不知道具体的含义,代码里面也没看出端倪.)

每一个接口都要有一个GUID属性(我当时上学的时候,把他叫属性属性,或者定制属性,现在也不清楚到底叫什么..).你可以用guidgen.exe来产生一个GUID值.

 

4、 参考以下代码及MSDN中COM 类示例(C# 编程指南):
  using System;
  using System.Collections.Generic;
  using System.Text;
  using System.Runtime.InteropServices;
  namespace Youtube
  {
  [Guid("FA1BEAD8-D5E2-4a70-ACDF-0A7FB4DA17FD")]
  public interface IYoutubeService
  {
  void UploadFile();
  }
  [Guid("2BD4711C-CAC0-4df5-B167-447FCD00D55C"),
  ClassInterface(ClassInterfaceType.AutoDispatch)]
  public class YoutubeService : IYoutubeService
  {
  public void UploadFile()
  {
  Console.WriteLine("My Com Test!");
  }
  }
  }
5、 编译,这时候会生成*.dll文件和*.tlb文件

 

为了(真正)导出COM对象,程序集还需要强命名,可以用sn.exe生成一个StrongName:

sn -k Youtube_Key.snk

在AssemblyInfo.cs文件里面修改:

[assembly: AssemblyKeyFile("Youtube_Key.snk")]

编译这个对象.会产生一个tlb文件,通过这个可以使Managed代码和Native代码都能访问你的COM对象.

6、 创建一个vc++的控制台项目,将*.tlb文件拷贝到vc++工程目录下

7、 Vc++代码如下:
#import "Youtube.tlb"
#include <stdio.h>
#include <comutil.h>
#pragma comment(lib,"comsuppw.lib")
using namespace Youtube;
int main(int argc, char* argv[])
{
    CoInitialize(NULL);
    try
    {
        IYoutubeServicePtr service( __uuidof( YoutubeService ) );
        service->UploadFile();
    }
    catch (const _com_error& e)
    {
    }
    CoUninitialize();
    return 0;
}
8、编译程序,并把之前的*.dll文件拷贝到和生成exe一起,运行程序则测试ok!

 

参考:http://www.fengfly.com/plus/view-174204-1.html

http://www.codeproject.com/KB/COM/com_object_in_c_.aspx

http://blog.csdn.net/icefire999/archive/2004/05/29/20192.aspx