找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 3275|回复: 11

[分享] netload时注册dll并加载局部cui

[复制链接]
发表于 2015-4-2 18:56:48 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
本帖最后由 雪山飞狐(lzh) 于 2015-4-4 01:04 编辑

自2006版本以后,cad的用户界面变成了cui/cuix,使用局部cui可以简单的加载界面要素,比如菜单、工具栏
但cui的加载一直没有提供NetApi的版本,而Com库提供的该功能,问题是Com库通常要加载组件,使跨版本成为问题
那么有办法简单解决这个问题吗,显然反射可以,下面的代码就是基于这个想法的实现
AxObject类, Com对象代理类,封装了属性设置/读取和函数调用
  1. using System;using System.Collections.Generic;
  2. using System.Linq;
  3. using System.Text;
  4. using System.Reflection;
  5. using Autodesk.AutoCAD.ApplicationServices;
  6. using Autodesk.AutoCAD.DatabaseServices;

  7. namespace TlsCad.Runtime
  8. {
  9.     public class AxObject
  10.     {

  11.         public static AxObject AcadApplication
  12.         {
  13.             get { return new AxObject(Application.AcadApplication); }
  14.         }

  15.         public static AxObject Preferences
  16.         {
  17.             get { return new AxObject(Application.Preferences); }
  18.         }

  19.         public object Object
  20.         { protected set; get; }

  21.         protected Type _type;

  22.         protected AxObject()
  23.         { }

  24.         public AxObject(DBObject obj)
  25.             : this(obj.AcadObject)
  26.         { }

  27.         public AxObject(object value)
  28.         {
  29.             Object = value;
  30.             _type = Type.GetTypeFromHandle(Type.GetTypeHandle(Object));
  31.         }

  32.         public AxObjectList AsList()
  33.         {
  34.             return new AxObjectList(Object, _type);
  35.         }

  36.         public AxObject GetProperty(string propertyName)
  37.         {
  38.             try
  39.             {
  40.                 object obj =
  41.                     _type.InvokeMember(
  42.                     propertyName,
  43.                     BindingFlags.GetProperty,
  44.                     null,
  45.                     Object,
  46.                     new object[0]);
  47.                 if (obj != null)
  48.                     return new AxObject(obj);
  49.             }
  50.             catch
  51.             { }

  52.             return null;

  53.         }

  54.         public void SetProperty(string propertyName, object value)
  55.         {
  56.             try
  57.             {
  58.                 _type.InvokeMember(
  59.                     propertyName,
  60.                     BindingFlags.SetProperty,
  61.                     null,
  62.                     Object,
  63.                     new object[] { value });
  64.             }
  65.             catch
  66.             { }
  67.         }

  68.         public AxObject Invoke(string methodName, params object[] args)
  69.         {
  70.             try
  71.             {
  72.                 object obj = _type.InvokeMember(methodName, BindingFlags.InvokeMethod, null, Object, args);
  73.                 if (obj != null)
  74.                     return new AxObject(obj);
  75.             }
  76.             catch
  77.             { }

  78.             return null;

  79.         }

  80.         public override string ToString()
  81.         {
  82.             return Object.ToString();
  83.         }

  84.     }
  85. }

AxObjectList类
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Collections;

  6. namespace TlsCad.Runtime
  7. {
  8.     public class AxObjectList : AxObject,IEnumerable<AxObject>
  9.     {


  10.         internal AxObjectList(object value, Type type)
  11.         {
  12.             Object = value;
  13.             _type = type;
  14.         }

  15.         public AxObject this[int index]
  16.         {
  17.             get { return this.Invoke("Item", index); }
  18.         }

  19.         public AxObject this[string name]
  20.         {
  21.             get { return this.Invoke("Item", name); }
  22.         }

  23.         public int Count
  24.         {
  25.             get { return (int)this.GetProperty("Count").Object; }
  26.         }

  27.         public void ForEach(Action<AxObject> action)
  28.         {
  29.             for (int i = 0; i < Count; i++)
  30.                 action(this.Invoke("Item", i));
  31.         }

  32.         public IEnumerator<AxObject> GetEnumerator()
  33.         {
  34.             for (int i = 0; i < Count; i++)
  35.                 yield return this.Invoke("Item", i);
  36.         }

  37.         IEnumerator IEnumerable.GetEnumerator()
  38.         {
  39.             for (int i = 0; i < Count; i++)
  40.                 yield return this.Invoke("Item", i);
  41.         }

  42.     }
  43. }
AutoRegAessem类,自动注册dll的简化类,改写自kean
  1. using System;
  2. using System.IO;
  3. using System.Linq;
  4. using System.Reflection;

  5. using Autodesk.AutoCAD.DatabaseServices;
  6. using Autodesk.AutoCAD.Runtime;
  7. using Microsoft.Win32;


  8. namespace TlsCad.Runtime
  9. {


  10.     public enum AssemLoadType
  11.     {
  12.         Startting = 2,
  13.         ByCommand = 12,
  14.         Disabled = 20
  15.     }

  16.     [Serializable]
  17.     public struct AssemInfo
  18.     {
  19.         /// <summary>
  20.         /// 注册名
  21.         /// </summary>
  22.         public string Name;

  23.         /// <summary>
  24.         /// 程序集全名
  25.         /// </summary>
  26.         public string Fullname;

  27.         /// <summary>
  28.         /// 程序集路径
  29.         /// </summary>
  30.         public string Loader;

  31.         /// <summary>
  32.         /// 加载方式
  33.         /// </summary>
  34.         public AssemLoadType LoadType;

  35.         /// <summary>
  36.         /// 程序集说明
  37.         /// </summary>
  38.         public string Description;

  39.     }

  40.     [Serializable]
  41.     public class Command : IComparable<Command>
  42.     {

  43.         public string GlobalName;
  44.         public string LocalizedName;
  45.         public string GroupName;

  46.         public string TypeName;
  47.         public string MethodName;

  48.         public string Description;

  49.         public Command() { }

  50.         public Command(string globalName)
  51.         {
  52.             GlobalName = globalName;
  53.         }

  54.         #region IComparable<Command> 成员

  55.         int IComparable<Command>.CompareTo(Command other)
  56.         {
  57.             return this.GlobalName.CompareTo(other.GlobalName);
  58.         }

  59.         #endregion

  60.     }

  61.     public abstract class AutoRegAssem : IExtensionApplication
  62.     {

  63.         private AssemInfo _info = new AssemInfo();

  64.         public static Assembly CurrAssembly
  65.         {
  66.             get { return Assembly.GetCallingAssembly(); }
  67.         }

  68.         public static string Location
  69.         {
  70.             get { return CurrAssembly.Location; }
  71.         }

  72.         public static string Path
  73.         {
  74.             get
  75.             {
  76.                 DirectoryInfo di = new DirectoryInfo(Location).Parent;
  77.                 string path = di.FullName;
  78.                 if (path.LastIndexOf('\\') != path.Length - 1)
  79.                     path += '\\';
  80.                 return path;
  81.             }
  82.         }

  83.         public AutoRegAssem()
  84.         {

  85.             Assembly assem = Assembly.GetCallingAssembly();
  86.             _info.Loader = assem.Location;
  87.             _info.Fullname = assem.FullName;
  88.             _info.Name = assem.GetName().Name;
  89.             _info.LoadType = AssemLoadType.Startting;

  90.             if (!SearchForReg())
  91.             {
  92.                 RegApp();
  93.             }

  94.         }


  95.         #region Reg

  96.         private RegistryKey GetAcAppKey()
  97.         {

  98.             RegistryKey ackey =
  99.                 Registry.CurrentUser.OpenSubKey(
  100.                     HostApplicationServices.Current.RegistryProductRootKey, true);

  101.             return ackey.CreateSubKey("Applications");

  102.         }

  103.         private bool SearchForReg()
  104.         {

  105.             RegistryKey appkey = GetAcAppKey();
  106.             var regApps = appkey.GetSubKeyNames();
  107.             return regApps.Contains(_info.Name);

  108.         }

  109.         public void RegApp()
  110.         {

  111.             RegistryKey appkey = GetAcAppKey();
  112.             RegistryKey rk = appkey.CreateSubKey(_info.Name);
  113.             rk.SetValue("DESCRIPTION", _info.Fullname, RegistryValueKind.String);
  114.             rk.SetValue("LOADCTRLS", _info.LoadType, RegistryValueKind.DWord);
  115.             rk.SetValue("LOADER", _info.Loader, RegistryValueKind.String);
  116.             rk.SetValue("MANAGED", 1, RegistryValueKind.DWord);
  117.             appkey.Close();

  118.         }

  119.         #endregion

  120.         

  121.         #region IExtensionApplication 成员

  122.         public abstract void Initialize();

  123.         public abstract void Terminate();

  124.         #endregion

  125.     }
  126. }
调用方式
  1. [assembly: ExtensionApplication(typeof(TlsCad.Parts.MyArx))]
  2. [assembly: CommandClass(typeof(TlsCad.Parts.MyArx))]

  3. namespace TlsCad.Parts
  4. {
  5.     class MyArx : AutoRegAssem
  6.     {

  7.         public override void Initialize()
  8.         {

  9.             var files = AxObject.Preferences.GetProperty("Files");
  10.             var oldPath = files.GetProperty("SupportPath").ToString();
  11.             if (!oldPath.ToLower().Contains(Path.ToLower()))
  12.                 files.SetProperty("SupportPath", oldPath + ";" + Path);

  13.             var acapp = AxObject.AcadApplication;
  14.             var groups = acapp.GetProperty("MenuGroups").AsList();
  15.             var cui = groups["TlsCad"];

  16.             if (cui == null)
  17.             {
  18.                 cui = groups.Invoke("Load", "TlsCad.cui");
  19.                 var menus = cui.GetProperty("Menus").AsList();
  20.                 foreach (var menu in menus)
  21.                 {
  22.                     menus.Invoke(
  23.                         "InsertMenuInMenuBar",
  24.                         menu.GetProperty("Name"),
  25.                         "");
  26.                 }
  27.             }

  28.             SystemManager.Editor.WriteMessage("\nTlsPart Loading!......");

  29.         }

  30.         public override void Terminate()
  31.         {

  32.         }
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
 楼主| 发表于 2015-4-2 19:03:30 | 显示全部楼层
二、Com集合的处理
让AxObject类继承IEnumerable接口,可以实现集合的遍历
修改如下
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Reflection;
  6. using Autodesk.AutoCAD.ApplicationServices;
  7. using Autodesk.AutoCAD.DatabaseServices;
  8. using System.Collections;

  9. namespace TlsCad.Runtime
  10. {
  11.     public class AxObject: IEnumerable<AxObject>
  12.     {

  13.         public static AxObject AcadApplication
  14.         {
  15.             get { return new AxObject(Application.AcadApplication); }
  16.         }

  17.         public static AxObject Preferences
  18.         {
  19.             get { return new AxObject(Application.Preferences); }
  20.         }

  21.         public object Value
  22.         { private set; get; }

  23.         Type _type;

  24.         public AxObject(DBObject obj) :this(obj.AcadObject)
  25.         {   }

  26.         public AxObject(object value)
  27.         {
  28.             Value = value;
  29.             _type = Type.GetTypeFromHandle(Type.GetTypeHandle(Value));
  30.         }

  31.         public AxObject GetProperty(string propertyName)
  32.         {
  33.             try
  34.             {
  35.                 object obj =
  36.                     _type.InvokeMember(
  37.                         propertyName,
  38.                         BindingFlags.GetProperty,
  39.                         null,
  40.                         Value,
  41.                         new object[0]);
  42.                 if (obj != null)
  43.                     return new AxObject(obj);
  44.             }
  45.             catch
  46.             { }

  47.             return null;

  48.         }

  49.         public void SetProperty(string propertyName, object value)
  50.         {
  51.             try
  52.             {
  53.                 _type.InvokeMember(
  54.                     propertyName,
  55.                     BindingFlags.SetProperty,
  56.                     null,
  57.                     value,
  58.                     new object[] { value });
  59.             }
  60.             catch
  61.             { }
  62.         }

  63.         public AxObject Invoke(string methodName, params object[] args)
  64.         {
  65.             try
  66.             {
  67.                 object obj =
  68.                     _type.InvokeMember(
  69.                         methodName,
  70.                         BindingFlags.InvokeMethod,
  71.                         null,
  72.                         Value,
  73.                         args);
  74.                 if (obj != null)
  75.                     return new AxObject(obj);
  76.             }
  77.             catch
  78.             { }

  79.             return null;

  80.         }

  81.         public void ForEach(Action<AxObject> action)
  82.         {
  83.             int count = (int)this.GetProperty("Count").Value;
  84.             for (int i = 0; i < count; i++)
  85.                 action(this.Invoke("Item", i));
  86.         }

  87.         public IEnumerator<AxObject> GetEnumerator()
  88.         {
  89.             int count = (int)this.GetProperty("Count").Value;
  90.             for (int i = 0; i < count; i++)
  91.                 yield return this.Invoke("Item", i);
  92.         }

  93.         IEnumerator IEnumerable.GetEnumerator()
  94.         {
  95.             int count = (int)this.GetProperty("Count").Value;
  96.             for (int i = 0; i < count; i++)
  97.                 yield return this.Invoke("Item", i);
  98.         }
  99.     }
  100. }
调用代码如下修改
  1.             if (cui == null)
  2.             {
  3.                 cui = groups.Invoke("Load", "TlsCad.cui");
  4.                 var menus = cui.GetProperty("Menus");
  5.                 foreach (var menu in menus)
  6.                 {
  7.                     menus.Invoke(
  8.                         "InsertMenuInMenuBar",
  9.                         menu.GetProperty("Name").Value,
  10.                         "");
  11.                 }
  12.             }
复制代码
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 3198个

财富等级: 富可敌国

发表于 2015-4-2 19:38:17 | 显示全部楼层
太高深了,大师可以出个怎么将C#源码编译成DLL的教材么? 经常见到有人分享源码,但不会编译,也就没用处了

点评

http://bbs.mjtd.com/thread-78291-1-1.html 可以看看这里  详情 回复 发表于 2015-4-3 12:57
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 264个

财富等级: 日进斗金

发表于 2015-4-2 22:14:17 来自手机 | 显示全部楼层
2012以下版本 loadctrl =2 无效,只有 4 或 8模式有效

点评

我的2008用2正常 再低就不推荐用NetApi了  详情 回复 发表于 2015-4-3 12:58
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-4-3 12:57:17 | 显示全部楼层
lucas3 发表于 2015-4-2 19:38
太高深了,大师可以出个怎么将C#源码编译成DLL的教材么? 经常见到有人分享源码,但不会编译,也就没用处了

http://bbs.mjtd.com/thread-78291-1-1.html
可以看看这里
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-4-3 12:58:29 | 显示全部楼层
iLisp 发表于 2015-4-2 22:14
2012以下版本 loadctrl =2 无效,只有 4 或 8模式有效

我的2008用2正常
再低就不推荐用NetApi了

点评

2010上 2 模式始终无效,但有CommandMethod定义的命令可以启动  详情 回复 发表于 2015-4-3 13:14
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 264个

财富等级: 日进斗金

发表于 2015-4-3 13:14:11 来自手机 | 显示全部楼层
雪山飞狐_lzh 发表于 2015-4-3 12:58
我的2008用2正常
再低就不推荐用NetApi了


2010上 2 模式始终无效,但CommandMethod定义的命令可以启动

点评

..我现在用过的最高版本也就2011 呵呵  发表于 2015-4-4 01:06
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

发表于 2015-4-4 01:05:43 | 显示全部楼层
添加AxObjectList类以支持集合类,一楼代码已更新
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

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

本版积分规则

QQ|申请友链|Archiver|手机版|小黑屋|辽公网安备|晓东CAD家园 ( 辽ICP备15016793号 )

GMT+8, 2024-6-9 11:08 , Processed in 0.433352 second(s), 47 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表