我使用.NET Reflector从AutoCAD interop .dll重新创建了_DAcadApplicationEvents接口,并且我的代码适用于AutoCAD 2010.问题是我需要这个与AutoCAD 2006兼容,直到2012年和前进。我正在运行.NET 4.0,因此使用Embed Interop Type设置为true以确保我的Application对象正确解析到运行时而不需要反射调用方法,但我似乎无法找到一种方法来使事件接口无需工作GUID中的硬编码(特定于程序集)。
这是我从原始AutoDesk.AutoCAD.Interop.dll创建的自定义界面:
<ComImport(), Guid("1F893620-C96D-4361-BBAF-A61D4144B7F8"), TypeLibType(CShort(&H1010))>
Public Interface _DAcadApplicationEventsClone
<MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime), DispId(1)>
Sub SysVarChanged(<[In](), MarshalAs(UnmanagedType.BStr)> ByVal SysvarName As String, <[In](),
MarshalAs(UnmanagedType.Struct)> ByVal newVal As Object)
<MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime), DispId(8)>
Sub BeginQuit(<[In](), Out()> ByRef Cancel As Boolean)
End Interface
以这种方式创建Application对象:
Public Application As Object
Application = Marshal.GetActiveObject("AutoCAD.Application")
接下来,我使用IConnectionPoint连接到克隆的界面:
Dim acGUID As New Guid(GetInterfaceGUID())
Dim acConnectionPoint As ComTypes.IConnectionPoint = Nothing
TryCast(Application, ComTypes.IConnectionPointContainer).FindConnectionPoint(acGUID, acConnectionPoint)
Dim acSinkCookie As Integer
acConnectionPoint.Advise(Me, acSinkCookie)
正如您所看到的,我正在运行一个名为“GetInterfaceGUID”的函数来动态搜索正确的GUID,具体取决于系统上安装的AutoCAD版本。但是,如果返回的GUID与接口上的硬编码GUID不匹配,则无论如何都无法正常工作。我已经尝试了不同的反射方法来使用System._ComObject,这是我唯一能够接近的方法。我觉得我已经接近成功了,并且在这一点上会感激任何意见。提前谢谢。
-Locke
答案 0 :(得分:0)
正如您所发现的,AutoCAD COM Interop是版本甚至位数(32位/ 64位)相关。为什么不使用AutoCAD .NET应用程序事件来解决这些问题,如下所示?
using System;
using System.Text;
using System.Linq;
using System.Xml;
using System.Reflection;
using System.ComponentModel;
using System.Collections;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media.Imaging;
using System.Windows.Forms;
using System.IO;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Windows;
using AcadApplication = Autodesk.AutoCAD.ApplicationServices.Application;
using AcadDocument = Autodesk.AutoCAD.ApplicationServices.Document;
using AcadWindows = Autodesk.AutoCAD.Windows;
namespace AcadNetAddinByVS2010
{
public class AppEvents1
{
bool mSuppressMsgOutput = false;
void OptionalMessageOutput(EventArgs obj, string eventName)
{
if (!mSuppressMsgOutput)
{
string msg = string.Format("Info about the {0} event:{1}", eventName, Environment.NewLine);
PropertyInfo[] piArr = obj.GetType().GetProperties();
foreach (PropertyInfo pi in piArr)
{
string attValue = pi.GetValue(obj, null).ToString();
msg += string.Format("\t{0}: {1}{2}", pi.Name, attValue, Environment.NewLine);
}
MessageBox.Show(msg, "Event: " + eventName, MessageBoxButtons.OK, MessageBoxIcon.Information);
System.Diagnostics.Debug.Write(msg);
}
}
public void Register()
{
AcadApplication.SystemVariableChanging += AppEvent_SystemVariableChanging_Handler;
AcadApplication.SystemVariableChanged += AppEvent_SystemVariableChanged_Handler;
AcadApplication.QuitWillStart += AppEvent_QuitWillStart_Handler;
AcadApplication.QuitAborted += AppEvent_QuitAborted_Handler;
AcadApplication.PreTranslateMessage += AppEvent_PreTranslateMessage_Handler;
AcadApplication.LeaveModal += AppEvent_LeaveModal_Handler;
AcadApplication.Idle += AppEvent_Idle_Handler;
AcadApplication.EnterModal += AppEvent_EnterModal_Handler;
AcadApplication.DisplayingOptionDialog += AppEvent_DisplayingOptionDialog_Handler;
AcadApplication.DisplayingDraftingSettingsDialog += AppEvent_DisplayingDraftingSettingsDialog_Handler;
AcadApplication.DisplayingCustomizeDialog += AppEvent_DisplayingCustomizeDialog_Handler;
AcadApplication.BeginQuit += AppEvent_BeginQuit_Handler;
}
public void UnRegister()
{
AcadApplication.SystemVariableChanging -= AppEvent_SystemVariableChanging_Handler;
AcadApplication.SystemVariableChanged -= AppEvent_SystemVariableChanged_Handler;
AcadApplication.QuitWillStart -= AppEvent_QuitWillStart_Handler;
AcadApplication.QuitAborted -= AppEvent_QuitAborted_Handler;
AcadApplication.PreTranslateMessage -= AppEvent_PreTranslateMessage_Handler;
AcadApplication.LeaveModal -= AppEvent_LeaveModal_Handler;
AcadApplication.Idle -= AppEvent_Idle_Handler;
AcadApplication.EnterModal -= AppEvent_EnterModal_Handler;
AcadApplication.DisplayingOptionDialog -= AppEvent_DisplayingOptionDialog_Handler;
AcadApplication.DisplayingDraftingSettingsDialog -= AppEvent_DisplayingDraftingSettingsDialog_Handler;
AcadApplication.DisplayingCustomizeDialog -= AppEvent_DisplayingCustomizeDialog_Handler;
AcadApplication.BeginQuit -= AppEvent_BeginQuit_Handler;
}
public void AppEvent_BeginQuit_Handler(object sender, EventArgs e)
{
OptionalMessageOutput(e, "BeginQuit");
}
public void AppEvent_DisplayingCustomizeDialog_Handler(object sender, TabbedDialogEventArgs e)
{
OptionalMessageOutput(e, "DisplayingCustomizeDialog");
}
public void AppEvent_DisplayingDraftingSettingsDialog_Handler(object sender, TabbedDialogEventArgs e)
{
OptionalMessageOutput(e, "DisplayingDraftingSettingsDialog");
}
public void AppEvent_DisplayingOptionDialog_Handler(object sender, TabbedDialogEventArgs e)
{
OptionalMessageOutput(e, "DisplayingOptionDialog");
}
public void AppEvent_EnterModal_Handler(object sender, EventArgs e)
{
OptionalMessageOutput(e, "EnterModal");
}
public void AppEvent_Idle_Handler(object sender, EventArgs e)
{
OptionalMessageOutput(e, "Idle");
}
public void AppEvent_LeaveModal_Handler(object sender, EventArgs e)
{
OptionalMessageOutput(e, "LeaveModal");
}
public void AppEvent_PreTranslateMessage_Handler(object sender, PreTranslateMessageEventArgs e)
{
OptionalMessageOutput(e, "PreTranslateMessage");
}
public void AppEvent_QuitAborted_Handler(object sender, EventArgs e)
{
OptionalMessageOutput(e, "QuitAborted");
}
public void AppEvent_QuitWillStart_Handler(object sender, EventArgs e)
{
OptionalMessageOutput(e, "QuitWillStart");
}
public void AppEvent_SystemVariableChanged_Handler(object sender, Autodesk.AutoCAD.ApplicationServices.SystemVariableChangedEventArgs e)
{
OptionalMessageOutput(e, "SystemVariableChanged");
}
public void AppEvent_SystemVariableChanging_Handler(object sender, Autodesk.AutoCAD.ApplicationServices.SystemVariableChangingEventArgs e)
{
OptionalMessageOutput(e, "SystemVariableChanging");
}
}
}
以下是所选IExtensionApplication实现中的事件注册代码:
#region Namespaces
using System;
using System.Text;
using System.Linq;
using System.Xml;
using System.Reflection;
using System.ComponentModel;
using System.Collections;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media.Imaging;
using System.Windows.Forms;
using System.Drawing;
using System.IO;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Windows;
using AcadApplication = Autodesk.AutoCAD.ApplicationServices.Application;
using AcadDocument = Autodesk.AutoCAD.ApplicationServices.Document;
using AcadWindows = Autodesk.AutoCAD.Windows;
#endregion
namespace AcadNetAddinByVS2010
{
public class ExtApp : IExtensionApplication
{
#region IExtensionApplication Members
public void Initialize()
{
//TODO: add code to run when the ExtApp initializes. Here are a few examples:
// Checking some host information like build #, a patch or a particular Arx/Dbx/Dll;
// Creating/Opening some files to use in the whole life of the assembly, e.g. logs;
// Adding some ribbon tabs, panels, and/or buttons, when necessary;
// Loading some dependents explicitly which are not taken care of automatically;
// Subscribing to some events which are important for the whole session;
// Etc.
mAppEvents1.Register();
}
public void Terminate()
{
//TODO: add code to clean up things when the ExtApp terminates. For example:
// Closing the log files;
// Deleting the custom ribbon tabs/panels/buttons;
// Unloading those dependents;
// Un-subscribing to those events;
// Etc.
mAppEvents1.UnRegister();
}
#endregion
AppEvents1 mAppEvents1 = new AppEvents1();
}
}