using System;
using System.Runtime.InteropServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.EditorInput;
#pragma warning disable 0618
// This line is not mandatory, but improves loading performances
[assembly: CommandClass(typeof(GetProperties.MyCommands))]
namespace GetProperties
{
#region COMIDispatch
[ComImport()]
[Guid("00020400-0000-0000-C000-000000000046")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IDispatch
{
[PreserveSig]
int GetTypeInfoCount(out int Count);
[PreserveSig]
int GetTypeInfo
(
[MarshalAs(UnmanagedType.U4)] int iTInfo,
[MarshalAs(UnmanagedType.U4)] int lcid,
out System.Runtime.InteropServices.ComTypes.ITypeInfo typeInfo
);
[PreserveSig]
int GetIDsOfNames
(
ref Guid riid,
[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr)]
string[] rgsNames,
int cNames,
int lcid,
[MarshalAs(UnmanagedType.LPArray)] int[] rgDispId
);
[PreserveSig]
int Invoke
(
int dispIdMember,
ref Guid riid,
uint lcid,
ushort wFlags,
ref System.Runtime.InteropServices.ComTypes.DISPPARAMS pDispParams,
out object pVarResult,
ref System.Runtime.InteropServices.ComTypes.EXCEPINFO pExcepInfo,
IntPtr[] pArgErr
);
}
public enum MethodType
{
Method = 0,
Property_Getter = 1,
Property_Putter = 2,
Property_PutRef = 3
}
public struct MethodInformation
{
public string m_strName;
public string m_strDocumentation;
public MethodType m_method_type;
}
class COMIDispatch
{
// This static function returns an array containing
// information of all public methods of a COM object.
// Note that the COM object must implement the IDispatch
// interface in order to be usable in this function.
public static MethodInformation[] GetMethodInformation(object com_obj)
{
IDispatch pDispatch = null;
try {
// Obtain the COM IDispatch interface from the input com_obj object.
// Low-level-wise this causes a QueryInterface() to be performed on
// com_obj to obtain the IDispatch interface from it.
pDispatch = (IDispatch)com_obj;
}
catch (System.InvalidCastException ex) {
// This means that the input com_obj
// does not support the IDispatch
// interface.
return null;
}
// Obtain the ITypeInfo interface from the object via its
// IDispatch.GetTypeInfo() method.
System.Runtime.InteropServices.ComTypes.ITypeInfo pTypeInfo = null;
// Call the IDispatch.GetTypeInfo() to obtain an ITypeInfo interface
// pointer from the com_obj.
// Note that the first parameter must be 0 in order to
// obtain the Type Info of the current object.
pDispatch.GetTypeInfo
(
0,
0,
out pTypeInfo
);
// If for some reason we are not able to obtain the
// ITypeInfo interface from the IDispatch interface
// of the COM object, we return immediately.
if (pTypeInfo == null) {
return null;
}
// Get the TYPEATTR (type attributes) of the object
// via its ITypeInfo interface.
IntPtr pTypeAttr = IntPtr.Zero;
System.Runtime.InteropServices.ComTypes.TYPEATTR typeattr;
// The TYPEATTR is returned via an IntPtr.
pTypeInfo.GetTypeAttr(out pTypeAttr);
// We must convert the IntPtr into the TYPEATTR structure
// defined in the System.Runtime.InteropServices.ComTypes
// namespace.
typeattr = (System.Runtime.InteropServices.ComTypes.TYPEATTR)Marshal.PtrToStructure
(
pTypeAttr,
typeof(System.Runtime.InteropServices.ComTypes.TYPEATTR)
);
// Release the resources related to the obtaining of the
// COM TYPEATTR structure from an ITypeInfo interface.
// From now onwards, we will only work with the
// System.Runtime.InteropServices.ComTypes.TYPEATTR
// structure.
pTypeInfo.ReleaseTypeAttr(pTypeAttr);
pTypeAttr = IntPtr.Zero;
// The TYPEATTR.guid member indicates the default interface implemented
// by the COM object.
Guid defaultInterfaceGuid = typeattr.guid;
MethodInformation[] method_information_array = new MethodInformation[typeattr.cFuncs];
// The TYPEATTR.cFuncs member indicates the total number of methods
// that the current COM object implements.
for (int i = 0; i < (typeattr.cFuncs); i++) {
// We loop through the number of methods.
System.Runtime.InteropServices.ComTypes.FUNCDESC funcdesc;
IntPtr pFuncDesc = IntPtr.Zero;
string strName;
string strDocumentation;
int iHelpContext;
string strHelpFile;
// During each loop, we use the ITypeInfo.GetFuncDesc()
// method to obtain a FUNCDESC structure which describes
// the current method indexed by "i".
pTypeInfo.GetFuncDesc(i, out pFuncDesc);
// The FUNCDESC structure is returned as an IntPtr.
// We need to convert it into a FUNCDESC structure
// defined in the System.Runtime.InteropServices.ComTypes
// namespace.
funcdesc = (System.Runtime.InteropServices.ComTypes.FUNCDESC)Marshal.PtrToStructure
(
pFuncDesc,
typeof(System.Runtime.InteropServices.ComTypes.FUNCDESC)
);
// The FUNCDESC.memid contains the member id of the current function
// in the Type Info of the object.
// Use the ITypeInfo.GetDocumentation() with reference to memid
// to obtain information for this function.
pTypeInfo.GetDocumentation
(
funcdesc.memid,
out strName,
out strDocumentation,
out iHelpContext,
out strHelpFile
);
// Fill up the appropriate method_information_array element
// with field information.
method_information_array[i].m_strName = strName;
method_information_array[i].m_strDocumentation = strDocumentation;
if (funcdesc.invkind == System.Runtime.InteropServices.ComTypes.INVOKEKIND.INVOKE_FUNC) {
method_information_array[i].m_method_type = MethodType.Method;
} else if (funcdesc.invkind == System.Runtime.InteropServices.ComTypes.INVOKEKIND.INVOKE_PROPERTYGET) {
method_information_array[i].m_method_type = MethodType.Property_Getter;
} else if (funcdesc.invkind == System.Runtime.InteropServices.ComTypes.INVOKEKIND.INVOKE_PROPERTYPUT) {
method_information_array[i].m_method_type = MethodType.Property_Putter;
} else if (funcdesc.invkind == System.Runtime.InteropServices.ComTypes.INVOKEKIND.INVOKE_PROPERTYPUTREF) {
method_information_array[i].m_method_type = MethodType.Property_PutRef;
}
// The ITypeInfo.ReleaseFuncDesc() must be called
// to release the (unmanaged) memory of the FUNCDESC
// returned in pFuncDesc (an IntPtr).
pTypeInfo.ReleaseFuncDesc(pFuncDesc);
pFuncDesc = IntPtr.Zero;
}
return method_information_array;
}
}
#endregion
public class MyCommands
{
[CommandMethod("GetProps")]
public void GetProps()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
if (doc == null) return;
Editor ed = doc.Editor;
PromptEntityResult rs = ed.GetEntity("\nВыберите примитив: ");
if (rs.Status != PromptStatus.OK) return;
using (Entity ent = rs.ObjectId.Open(OpenMode.ForRead) as Entity) {
object ob = ent.AcadObject;
MethodInformation[] mis = COMIDispatch.GetMethodInformation(ob);
foreach (MethodInformation mi in mis) {
if (mi.m_method_type == MethodType.Property_Getter) {
ed.WriteMessage("\n{0} ==> {1}", mi.m_strName, mi.m_strDocumentation);
}
}
}
}
}
}