使用C#进行AutoCAD二次开发,有时候由于C#接口不够完善,或者低版本AutoCAD中的接口缺少,有些工作不能直接通过C#接口来实现,所以需要通过P/Invoke的方式调用AutoCAD的其他DLL中的接口来实现。

最常见的是向AutoCAD发送同步命令,在高版本的AutoCAD.NET接口中好像是可以发送同步命令了(据说是从2014或2015开始是可以了,不过我没有进行验证),但在低版本AutoCAD.NET中是没有发送同步命令接口的,SendStringToExecute和COM接口中的SendCommand都是异步操作,只有通过acedCmd、acedCommand、acedPostCommand才可能发送同步命令,这三个接口在AutoCAD2013之前是在acad.exe中的,而从AutoCAD2013开始放到了accore.dll中,并且acedPostCommand这个接口是官方没有公布但实际是可以使用的。

正常通过P/Invoke方式调用需要进行以下声明:

AutoCAD2013以前的版本

[System.Security.SuppressUnmanagedCodeSecurity]
[DllImport("acad.exe", EntryPoint = "acedCmd", CallingConvention = CallingConvention.Cdecl)]
private static extern int acedCmd(IntPtr vlist);
[DllImport("acad.exe", EntryPoint = "acedCommand")]
private static extern int acedCommand(IntPtr vlist);//CAD2008和2008以前版本中的EntryPoint名称和2009以及2009之后的版本不一样
[DllImport("acad.exe", CharSet = CharSet.Auto, EntryPoint = "?acedPostCommand@@YAHPB_W@Z", CallingConvention = CallingConvention.Cdecl)]
private static extern int acedPostCommand(string strExpr);//CAD2008之后的版本中
[DllImport("acad.exe", CharSet = CharSet.Auto, EntryPoint = "?acedPostCommand@@YAHPEB_W@Z", CallingConvention = CallingConvention.Cdecl)]
private static extern int acedPostCommand(string strExpr);

AutoCAD2013及更新版本

[System.Security.SuppressUnmanagedCodeSecurity]
[DllImport("accore.dll", EntryPoint = "acedCmd", CallingConvention = CallingConvention.Cdecl)]
private static extern int acedCmd(IntPtr vlist);[DllImport("accore.dll", EntryPoint = "acedCommand")]
private static extern int acedCommand(IntPtr vlist);//CAD2008和2008以前版本中的EntryPoint名称和2009以及2009之后的版本不一样
[DllImport("accore.dll", CharSet = CharSet.Auto, EntryPoint = "?acedPostCommand@@YAHPB_W@Z", CallingConvention = CallingConvention.Cdecl)]
private static extern int acedPostCommand(string strExpr);
//CAD2008之后的版本中
[DllImport("accore.dll", CharSet = CharSet.Auto, EntryPoint = "?acedPostCommand@@YAHPEB_W@Z", CallingConvention = CallingConvention.Cdecl)]
private static extern int acedPostCommand(string strExpr);

使用时直接进行调用即可:

ResultBuffer rb = new ResultBuffer();
rb.Add(new TypedValue((int)LispDataType.Text, "_.mycmd"));
int i = acedCmd(rb.UnmanagedObject);

要注意的是这些接口不能使用Loadlibrary的方式进行调用,因为Loadlibrary会把指定的DLL或EXE进行加载,加载后应该和当前程序所寄存的AutoCAD主进程不是一回事了,调用会有问题或调用结果达不到预期效果。

今天要介绍的是另外一种不使用P/Invoke方式就可以在自己的插件中调用acad.exe或accore.dll中接口的方法,主要思路如下:

1、获取当前进程Process,因为插件是被加载到AutoCAD中运行的,所以获取到的是AutoCAD进程。

2、获取当前进程加载的所有模块ProcessModuleCollection。

3、遍历ProcessModuleCollection找到自己要调用的接口所在的模块ProcessModule。

4、声明一个和要调用的接口格式相同的委托。

5、获取ProcessModule的EntryPointAddress,然后使用Marshal.GetDelegateForFunctionPointer方法根据函数句柄得到一个委托实例。

6、调用委托实例进行执行即可。

以acedPostCommand为例完整代码如下:

//此处声明的委托和acedPostCommand(string strExpr)不相同是因为经过测试,如果参数声明为string类型,调用的时候传送到CAD的命令是乱码
public delegate int DelegateAcedPostCommand(byte[] cmd);
static DelegateAcedPostCommand pc;public void ShowMsg()
{//不同版本接口所在的程序模块不同string mdName = Application.Version.Major >= 19 ? "accore.dll" : "acad.exe";//CAD2007和2008中接口入口点名称不一样,2007以前的没有看,想看的可以用depends工具查看string apiName = (Application.Version.Major >= 17 && Application.Version.Minor <= 1) ? "?acedPostCommand@@YAHPB_W@Z" : "?acedPostCommand@@YAHPEB_W@Z";//获取当前CAD进程Process pro = Process.GetCurrentProcess();//获取CAD加载的所有程序模块(引用了什么DLL、EXE)ProcessModuleCollection pmc = pro.Modules;IntPtr iptr = IntPtr.Zero;for (int i = 0; i < pmc.Count; i++){ProcessModule pm = pmc[i];if (pm.ModuleName == mdName){iptr = pm.EntryPointAddress;break;}}if (iptr != IntPtr.Zero){pc = (DelegateAcedPostCommand)Marshal.GetDelegateForFunctionPointer(iptr, typeof(DelegateAcedPostCommand));if (pc != null){string str = "_.remmenu\n";//此处要把字符串使用Unicode编码转换为byte[],然后再传入委托接口,不然到CAD之后会乱码byte[] bytes = Encoding.Unicode.GetBytes(str);int i = pc.Invoke(bytes);}}
}        

转载于:https://www.cnblogs.com/bomb12138/p/5913983.html

AutoCAD.NET 不使用P/Invoke方式调用acad.exe或accore.dll中的接口(如acedCommand、acedPostCommand等)...相关推荐

  1. C# 使用GET和POST(v1签名方式)以及SDK的方式调用腾讯云人像动漫化接口,包含设置代理

    声明:此内容仅供学习交流使用,不用于商业用途,如果涉及侵权,联系作者删除. 最近在调用腾讯云的人像动漫化接口,感觉挺好玩的,自己去看文档写了一下,遇到了各种问题,最后都解决了 ,遇到最多的就是签名错误 ...

  2. AUTOCAD 每次打开一个图纸都重新运行程序ACAD.EXE

    这个问题网上很多答案,我来总结下: 1.SDI设置0,程序默认单开程序是LAUNCHER,在目录: 2.如果在安装新版本的cad之后,你才卸载旧版本,那么你会发现打开后,提示找不到旧版本的程序,所以, ...

  3. js方式调用php_javascript调用PHP和PHP调用javascript的方法

    javascript调用PHP和PHP调用javascript的方法 发布时间:2020-06-22 17:03:14 来源:亿速云 阅读:262 作者:Leah 这篇文章将为大家详细讲解有关java ...

  4. js方式调用php_举例说明JS调用PHP和PHP调用JS的方法

    举例说明JS调用PHP和PHP调用JS的方法 在学习任何一门编程语言,我们都会听到调用这个词,那么,在javascript中是如何调用php的呢?在php中也可以调用js吗?下面就让我们一起来看看吧. ...

  5. Java中实现接口的三种方式您造吗?

    本文介绍了Java中实现接口的三种方式:常规实现方式.匿名内部类和 Lambda表达式实现方式.希望已经了解的同学可以重新温习一下,不了解的同学则从中受益! Java中接口最常规的实现方式 同学们都会 ...

  6. autoCAD在win10闪退,修改acad.exe.config文件

    1.重新注册法 打开注册表编辑器,定位到ROOT\installer\Products\7D2F的两个键值并删除C:\ ProgramData\FLEXnet文件夹. 重新激活后就可以正常使用了. 2 ...

  7. 从零开始使用InnoSteup进行程序打打包以及调用dll中的函数

    本示例涉及: 程序的打包和数字签名 InnoSetup的快速上手 以及一个产品从编译到安装的过程演示 首先,我提供一份InnoSteup的脚本文件,小伙伴们可直接使用这个脚本进行打包(不过得修改一下相 ...

  8. [js] axios为什么可以使用对象和函数两种方式调用?是如何实现的?

    [js] axios为什么可以使用对象和函数两种方式调用?是如何实现的? axios 源码 初始化 看源码第一步,先看package.json.一般都会申明 main 主入口文件. // packag ...

  9. Java,Axis方式调用WebService接口,支持多参数

    package com.demo.modules.si.util;import org.apache.axis.client.Call; import javax.xml.rpc.ParameterM ...

最新文章

  1. 漫画:什么是 “抽象工厂模式” ?
  2. CIO对虚拟化缺乏可预见成最大安全挑战
  3. Redis第二集:Linux下安装Redis和测试,包含命令代码和问题处理办法,超详细版
  4. Extjs 数据代理
  5. 从使用传统Web框架到切换到Spring Boot后的总结
  6. dqn系列梳理_系列论文阅读——DQN及其改进
  7. 【程序设计】接口在软件开发中的普遍用法
  8. FusionInsight怎么帮「宇宙行」建一个好的「云数据平台」?
  9. linux系统为什么很重要,为什么Linux系统始终取代不了Windows?这4个原因80%的人不知道!...
  10. SciPy 非线性方程求解 | Python技能树征题
  11. 修改linux kernel参数 semopm
  12. 《小团团团队》【Alpha】Scrum Meeting 3
  13. note8 升级android9,明年升!三星七大旗舰集体获安卓9.0认证:这阵容赢了!
  14. 网易云音乐云盘上传歌词的方法
  15. Linux桌面没有minidwep,ubuntu 12.04完整安装minidwep-gtk教程
  16. 计算机和小学科课题,《小学信息技术课堂有效教学的探索》课题研究方案
  17. 下载b站视频方法,pr去水印
  18. Firefox数据采集插件大全
  19. SkiaSharp 之 WPF 自绘 拖曳小球(案例版)
  20. 正负面情感词(中文 来源微博)

热门文章

  1. 同一局域网主机连接另一台电脑的虚拟机
  2. 群晖NAS如何实现双盘实时自动备份数据
  3. 你知道我什么时候最性感
  4. 基于Qt的音乐播放器制作
  5. [Unity Mirror] 同步
  6. vue codemirror 设置高度无效的解决办法
  7. UI设计中最重要的颜色
  8. 微软将于10月5日推出Office 2021,与Windows 11同年同月同日生
  9. Linux下查看系统硬件信息
  10. initialcontext java_缺少InitialContext定义时要使用的Java运行时异常