使用COM客户端调用.NET对象

原创 2006年06月02日 16:49:00

COM客户端为非托管环境,.NET对象是一个ClassLibrary
需要开放给非托管程序调用的.NET类库,最好实现一个public接口,否则每个托管类.NETFramework会生成一个类接口(名称为 _类名 )供COM客户端调用。
COM客户端在使用.NET对象的COM包装时,与使用普通COM组件相同。

.NET类库示例如下:

using System;
using System.Runtime.InteropServices;

namespace AAServer
{
 public interface IDumyWork
 {
  int Addfour( int number );
  int square( int number );
 }

 /// <summary>
 /// Summary description for Class1.
 /// </summary>
 [ClassInterface(ClassInterfaceType.None)]
 public class Class1: IDumyWork
 {
  public Class1()
  {
   //
   // TODO: Add constructor logic here
   //
  }
  #region IDumyWork Members

  public int Addfour(int number)
  {
   return number + 4;
  }

  public int square(int number)
  {
   return number * number;
  }

  #endregion
 }
}
上面代码中IDumyWork是类库公开的接口,Class1则相当于COM类对象,[ClassInterface(ClassInterfaceType.None)]则说明不生上面所述Class1的类接口。 

注册.NET对象为COM组件
AAServer类库编译成功后,使用命令:
    Regasm AAServer.dll /tlb AAServer.tlb
将注册COM组件,同时生成类型库tlb文件,这个文件在COM客户端引用COM组件时会用到。
    Regasm AAServer.dll /u    ; 取消组件注册

组件注册后,在OLEVIEW中可以看到其类型库信息如下:

// Generated .IDL file (by the OLE/COM Object Viewer)
//
// typelib filename: AAServer.tlb

[
  uuid(1AAA3E1C-A476-312A-BE2A-139DAE694F04),
  version(1.0),
  custom(90883F05-3D28-11D2-8F17-00A0C9A6186D, AAServer, Version=1.0.2344.25362, Culture=neutral, PublicKeyToken=c982512fd89d5c69)

]
library AAServer
{
    // TLib :     // TLib : Common Language Runtime Library : {BED7F4EA-1A96-11D2-8F08-00A0C9A6186D}
    importlib("mscorlib.tlb");
    // TLib : OLE Automation : {00020430-0000-0000-C000-000000000046}
    importlib("STDOLE2.TLB");

    // Forward declare all types defined in this typelib
    interface IDumyWork;

    [
      odl,
      uuid(79A96F30-31B6-39D1-A834-804DCBB4CACC),
      version(1.0),
      dual,
      oleautomation,
      custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, AAServer.IDumyWork)   

    ]
    interface IDumyWork : IDispatch {
        [id(0x60020000)]
        HRESULT Addfour(
                        [in] long number,
                        [out, retval] long* pRetVal);
        [id(0x60020001)]
        HRESULT square(
                        [in] long number,
                        [out, retval] long* pRetVal);
    };

    [
      uuid(D99C7A9B-3B90-3080-89CE-A42665B9725E),
      version(1.0),
      custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, AAServer.Class1)
    ]
    coclass Class1 {
        interface _Object;
        [default] interface IDumyWork;
    };
};
其中_Object是Class1的基类生成的类接口,与一般的COM组件类型库基本相同。
在OLEVIEW中object classes -> grouped by componect category -> .NET category中可以看到“AAServer.Class1”类打开后发现它不仅实现了IDumyWork,IUnknown,IDispatch接口外,还实现了IConnectionPointContainer,IManagedObject等接口。

为.NET类库添加强名称
这是要为.NET类库添加强名称并加入全局程序集缓存中,这样客户端在运行时,不必将.NET类库DLL拷到EXE目录下。
创建密钥对:
   sn -k AAServer.snk
生成密钥对,并将AAServer.snk考到project目录下,在AssemblyInfo.cs文件中添加:
[assembly: AssemblyKeyFile(@"../../AAServer.snk")]

重新编译类库,重新用regasm注册为COM组件,同时生成tlb类型库

加入全局程序集缓存:
   gacutil /i AAServer.dll
从全局程序集缓存删除:
   gacutil /u AAServer
加入全局程序集缓存后可以从C:/Winnt/assembly目录中看到"AAServer"项

COM客户端代码示例如下:

#include "stdafx.h"
#import "../AAServer/bin/Debug/AAServer.tlb"

inline void TESTHR( HRESULT _hr )
 { if FAILED(_hr) throw _com_error(_hr); }

int _tmain(int argc, _TCHAR* argv[])
{
 try
 {
  TESTHR( CoInitializeEx( NULL, COINIT_MULTITHREADED ) );

  AAServer::IDumyWorkPtr pwork = NULL;
  TESTHR( pwork.CreateInstance( "AAServer.Class1" ) );

  printf( "%d/n", pwork->Addfour( 10 ) );
  printf( "%d/n", pwork->square( 11 ) );
 }
 catch(_com_error e)
 {
  printf( "Exception:" );
  printf( e.ErrorMessage() );
 }
}
其中import语句引用的是刚才用regasm生成的COM类型库,使用类库的方法与使用普通COM组件并无差别
注意: 如果没有为.NET类库生成强名称并加入global assembly cache,那么pwork.CreateInstance( "AAServer.Class1" )会抛出"类型没有注册"的异常,除非将类库DLL考一份到EXE的目录下

C#中调用COM对象

C#中调用COM对象
  • u011162260
  • u011162260
  • 2015年05月22日 20:42
  • 1650

ATL 调用COM对象

创建完COM对象后,接下来是如何调用COM组件了。这里是在c++中的调用COM对象的方法。 创建COM对象一般有三种方法,正常创建一个对象,使用CoCreateInstance函数。若在远程系统中创建...
  • qq981932962
  • qq981932962
  • 2014年10月26日 00:43
  • 1367

PB 调用.NET COM组件

今天需要作一下pb引用.net的外接程序类。反复测试都没有成功。看到这篇文章解决了我的问题。在此感谢。综合我的碰壁经验。需要注意以下两点。 1..net项目需要勾选生成 com组件。 2....
  • pengdayong77
  • pengdayong77
  • 2015年06月30日 12:29
  • 655

vc中调用Com组件的方法详解

需求: 1.创建myCom.dll,该COM只有一个组件,两个接口:    IGetRes--方法Hello(),    IGetResEx--方法HelloEx() 2.在工程中导入组件或类型库 ...
  • qq1134993111
  • qq1134993111
  • 2015年04月25日 01:05
  • 1398

c++ 调用com的方式

一、在需要的文件中引入com对应
  • angellove156
  • angellove156
  • 2014年05月12日 17:31
  • 4470

COM对象与其基础RCW分开后就不能再使用

RCW是一个.NET和COM之间的桥梁,上述错误就是在于COM那一段的陆地消失了,你再想走着这桥,系统就报错了, 这种问题多半是COM对象被意外销毁或者没有抛出异常就崩溃导致。  解决问...
  • wmg494005678
  • wmg494005678
  • 2013年02月18日 11:12
  • 14137

一份完整的com组件服务端和客户端教程

最近在学com组件编程 苦于没有没有好的完整的教程 浪费大把时间,尤其是连接点那一块 ,网上很多文章都是 只显示代码的一段,本文更注重 项目的配置,完整如下 参考文章:              ...
  • wujinzbr
  • wujinzbr
  • 2015年04月16日 16:12
  • 483

VC调用COM组件的几种方法

这篇的内容也是我在使用COM组件的时候遇到困难后在网上找的一些调用的方法,以备后用。 1.首先创建一个COM组件:myCom.ocx    组件里面有一个普通接口:ImyCom   一个方法为:Hel...
  • u013823973
  • u013823973
  • 2014年12月26日 14:42
  • 1836

C++调用C# COM组件

原文地址 http://dearymz.blog.163.com/blog/static/2056574201191295525523/  感谢原作者分享 从C#创建COM,再到C++调用...
  • alaseven
  • alaseven
  • 2013年12月07日 13:51
  • 1249

COM组件开发(四)——VC++调用COM组件的方法

ActiveX 控件          对于ActiveX控件,可以在Visual Studio中使用ClassWizard的方法引入,在MFC项目中选择菜单“项目”——> “添加类”——>“Acti...
  • q5806622
  • q5806622
  • 2015年02月16日 15:15
  • 8073
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:使用COM客户端调用.NET对象
举报原因:
原因补充:

(最多只允许输入30个字)