乐筑天下

搜索
欢迎各位开发者和用户入驻本平台 尊重版权,从我做起,拒绝盗版,拒绝倒卖 签到、发布资源、邀请好友注册,可以获得银币 请注意保管好自己的密码,避免账户资金被盗
查看: 75|回复: 3

C#后绑定Com库全攻略

[复制链接]

72

主题

2726

帖子

9

银币

社区元老

Rank: 75Rank: 75Rank: 75

铜币
3014
发表于 2015-4-17 22:36:00 | 显示全部楼层 |阅读模式
使用C#做Com调用确实麻烦 比VB要麻烦多了,至于为什么使用后绑定显然是为了程序的通用性
然而Com对象在后绑定时不显示实际类型,只有使用反射
一、使用IDispatch接口
大多数Com类都是基于IDispatch接口,IDispatch接口在.Net中没有定义
下面是IDispatch接口的简易定义,没有Invoke函数的具体定义,那么Com类的方法调用就要获取实际类型
  1. using System;
  2. using System.Runtime.InteropServices;
  3. using System.Runtime.InteropServices.ComTypes;
  4. using System.Security;
  5. namespace TlsCad.Common.Runtime
  6. {
  7.     [ComImport, Guid("00020400-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
  8.     public interface IDispatch
  9.     {
  10.         [PreserveSig, Obsolete("Bad signature. Fix and verify signature before use.", true), SecurityCritical]
  11.         int GetTypeInfoCount();
  12.         [PreserveSig, SecurityCritical]
  13.         int GetTypeInfo([In] int index, [In] int lcid, [MarshalAs(UnmanagedType.Interface)] out ITypeInfo pTypeInfo);
  14.         [PreserveSig, SecurityCritical]
  15.         int GetIDsOfNames();
  16.         [PreserveSig, SecurityCritical]
  17.         int Invoke();
  18.     }
  19. }

回复

使用道具 举报

72

主题

2726

帖子

9

银币

社区元老

Rank: 75Rank: 75Rank: 75

铜币
3014
发表于 2015-4-17 22:36:00 | 显示全部楼层

二、自定义类AcVersion从注册表获取AutoCadCom库在GAC中的.Net程序集,以进行实际的反射,下面的代码主要应用于XP,如果在更高版本,你可能需要做些更改
  1. using System;
  2. using System.Collections.Generic;
  3. using Microsoft.Win32;
  4. using System.Text.RegularExpressions;
  5. using System.Reflection;
  6. using System.Runtime.InteropServices;
  7. using System.Runtime.InteropServices.ComTypes;
  8. namespace TlsCad.Common.Runtime
  9. {
  10.     public class AcVersion
  11.     {
  12.         public int Major
  13.         { private set; get; }
  14.         public int Minor
  15.         { private set; get; }
  16.         public double ProgId
  17.         {
  18.             get { return Major + Minor / 10.0; }
  19.         }
  20.         public string ProductName
  21.         { private set; get; }
  22.         public string ProductRootKey
  23.         { private set; get; }
  24.         private string _appAssemblyName;
  25.         private string _dbxAssemblyName;
  26.         public Assembly AppAssembly
  27.         { private set; get; }
  28.         public Assembly DbxAssembly
  29.         { private set; get; }
  30.         static string _appClassNameHead = "Autodesk.AutoCAD.Interop.";
  31.         static string _dbxClassNameHead = "Autodesk.AutoCAD.Interop.Common.";
  32.         ///
  33.         /// 获取Com对象的接口类型
  34.         ///
  35.         /// Com对象
  36.         /// 接口类型
  37.         public Type GetType(object obj)
  38.         {
  39.             IDispatch idisp = obj as IDispatch;
  40.             ITypeInfo t;
  41.             idisp.GetTypeInfo(0, 0, out t);
  42.             string name = Marshal.GetTypeInfoName(t);
  43.             return
  44.                 AppAssembly.GetType(_appClassNameHead + name) ??
  45.                 DbxAssembly.GetType(_dbxClassNameHead + name);
  46.         }
  47.         private static List _versions;
  48.         public static List Versions
  49.         {
  50.             get
  51.             {
  52.                 if (_versions == null)
  53.                 {
  54.                     string[] copys =
  55.                        Registry.LocalMachine
  56.                        .OpenSubKey(@"SOFTWARE\Autodesk\Hardcopy")
  57.                        .GetValueNames();
  58.                     _versions = new List();
  59.                     foreach (var rootkey in copys)
  60.                     {
  61.                         Regex r = new Regex(@"Autodesk\\AutoCAD\\R(\d+)\.(\d+)\\.*?");
  62.                         if (r.IsMatch(rootkey))
  63.                         {
  64.                             var gs = r.Match(rootkey).Groups;
  65.                             var ver =
  66.                                 new AcVersion
  67.                                 {
  68.                                     ProductRootKey = rootkey,
  69.                                     ProductName =
  70.                                         Registry.LocalMachine
  71.                                         .OpenSubKey("SOFTWARE")
  72.                                         .OpenSubKey(rootkey)
  73.                                         .GetValue("ProductName")
  74.                                         .ToString(),
  75.                                     Major = int.Parse(gs[1].Value),
  76.                                     Minor = int.Parse(gs[2].Value),
  77.                                 };
  78.                             ver.GetAssemblyName();
  79.                             _versions.Add(ver);
  80.                         }
  81.                     }
  82.                 }
  83.                 return _versions;
  84.             }
  85.         }
  86.         public static AcVersion FromApp(dynamic app)
  87.         {
  88.             var gs = Regex.Match(app.Version, @"(\d+)\.(\d+).*?").Groups;
  89.             int major = int.Parse(gs[1].Value);
  90.             int minor = int.Parse(gs[2].Value);
  91.             foreach (var ver in Versions)
  92.             {
  93.                 if (ver.Major == major && ver.Minor == minor)
  94.                     return ver;
  95.             }
  96.             return null;
  97.         }
  98.         public void LoadAssembly()
  99.         {
  100.             AppAssembly = Assembly.Load(_appAssemblyName);
  101.             DbxAssembly = Assembly.Load(_dbxAssemblyName);
  102.         }
  103.         private void GetAssemblyName()
  104.         {
  105.             _appAssemblyName = GetAssemblyName("AutoCad.Application", ProgId.ToString());
  106.             _dbxAssemblyName = GetAssemblyName("ObjectDBX.AxDbDocument", Major.ToString());
  107.         }
  108.         private string GetAssemblyName(string name, string id)
  109.         {
  110.             string clsId =
  111.                 Registry.ClassesRoot
  112.                 .OpenSubKey(name + "." + id)
  113.                 .OpenSubKey("CLSID")
  114.                 .GetValue("")
  115.                 .ToString();
  116.             return
  117.                 Registry.ClassesRoot
  118.                 .OpenSubKey(string.Format("CLSID\\{0}\\InprocServer32", clsId))
  119.                 .GetValue("Assembly").ToString();
  120.         }
  121.         public override string ToString()
  122.         {
  123.             return
  124.                 string.Format(
  125.                     "名称:{0}\n版本号:{1}\n注册表位置:{2}\nApp_Com类库:{3}\nDbx_Com类库:{4}",
  126.                     ProductName,
  127.                     ProgId,
  128.                     ProductRootKey,
  129.                     _appAssemblyName,
  130.                     _dbxAssemblyName);
  131.         }
  132.     }
  133. }

回复

使用道具 举报

72

主题

2726

帖子

9

银币

社区元老

Rank: 75Rank: 75Rank: 75

铜币
3014
发表于 2015-4-17 23:08:00 | 显示全部楼层
三、反射类AcObject继承于DynamicObject,以便在.Net4.0中使用动态特性
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Reflection;
  4. using System.Runtime.InteropServices;
  5. using System.Text.RegularExpressions;
  6. using System.Dynamic;
  7. namespace TlsCad.Common.Runtime
  8. {
  9.     public class AcObject : DynamicObject
  10.     {
  11.         public static dynamic Application
  12.         { private set; get; }
  13.         public static dynamic Preferences
  14.         {
  15.             get { return Application.Preferences; }
  16.         }
  17.         public static AcVersion Version
  18.         { private set; get; }
  19.         public Type Type
  20.         { private set; get; }
  21.         public object Value
  22.         { private set; get; }
  23.         #region Wrapper
  24.         protected AcObject() { }
  25.         public static dynamic Wrapper(dynamic obj, Type type)
  26.         {
  27.             if (obj != null && Marshal.IsComObject(obj))
  28.             {
  29.                 var wrapper =
  30.                     new AcObject
  31.                     {
  32.                         Value = obj,
  33.                         Type =
  34.                             Regex.IsMatch(type.Name, "^Acad.*?$") ?
  35.                             type.GetInterfaces()[0] :
  36.                             Version.GetType(obj)
  37.                     };
  38.                 if (wrapper.Type.GetMethod("Item") != null)
  39.                     return wrapper.AsItems();
  40.                 return wrapper;
  41.             }
  42.             else
  43.             {
  44.                 return obj;
  45.             }
  46.         }
  47.         public static dynamic Wrapper(object obj)
  48.         {
  49.             return Wrapper(obj, Version.GetType(obj));
  50.         }
  51.         #endregion
  52.         #region Invoke
  53.         private dynamic Invoke(MethodInfo mi, object[] args)
  54.         {
  55.             object obj = mi.Invoke(Value, args);
  56.             return Wrapper(obj, mi.ReturnType);
  57.         }
  58.         public dynamic InvokeMember(string name, params object[] args)
  59.         {
  60.             try
  61.             {
  62.                 //获取接口函数
  63.                 MethodInfo mi = Type.GetMethod(name);
  64.                 //配置参数
  65.                 var pars = mi.GetParameters();
  66.                 object[] realargs = new object[pars.Length];
  67.                 Array.Copy(args, realargs, args.Length);
  68.                 for (int i = args.Length; i  lst = new List { Invoke(mi, realargs) };
  69.                 for (int i = args.Length; i
  70.     {
  71.         internal AcItems() { }
  72.         public AcObject this[int id]
  73.         {
  74.             get { return (AcObject)this.InvokeMember("Item", id); }
  75.         }
  76.         public AcObject this[string id]
  77.         {
  78.             get { return (AcObject)this.InvokeMember("Item", id); }
  79.         }
  80.         public int Count
  81.         {
  82.             get { return (int)this.GetMember("Count").Value; }
  83.         }
  84.         public IEnumerator GetEnumerator()
  85.         {
  86.             int count = Count;
  87.             for (int i = 0; i  v.ToString()).ToArray()));
  88.             if (!AcObject.GetApp())
  89.                 AcObject.OpenApp(AcVersion.Versions[0]);
  90.             var pref = AcObject.Preferences;
  91.             var files = pref.Files;
  92.             var app = AcObject.Application;
  93.             app.Visible = true;
  94.             var doc = app.ActiveDocument;
  95.             var util = doc.Utility;
  96.             var res = util.GetEntity();
  97.             if (res != null)
  98.             {
  99.                 var obj = res[1];
  100.                 var pt = res[2];
  101.                 var p = obj.ObjectName;
  102.             }
  103.         }
回复

使用道具 举报

72

主题

2726

帖子

9

银币

社区元老

Rank: 75Rank: 75Rank: 75

铜币
3014
发表于 2015-4-17 23:09:00 | 显示全部楼层
这个很高端啊!给你点个赞!
回复

使用道具 举报

发表回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

  • 微信公众平台

  • 扫描访问手机版

  • 点击图片下载手机App

QQ|关于我们|小黑屋|乐筑天下 繁体中文

GMT+8, 2025-3-12 09:48 , Processed in 0.445794 second(s), 71 queries .

© 2020-2025 乐筑天下

联系客服 关注微信 帮助中心 下载APP 返回顶部 返回列表