.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Unable to cast COM object of type 'System.__ComObject' to class type 'Autodesk.AutoCAD.DatabaseServices.BlockReference'. Instances of types that represent COM components cannot be cast to types that d

10 REPLIES 10
Reply
Message 1 of 11
kmkxperia
768 Views, 10 Replies

Unable to cast COM object of type 'System.__ComObject' to class type 'Autodesk.AutoCAD.DatabaseServices.BlockReference'. Instances of types that represent COM components cannot be cast to types that d

I am trying use the Entity zig for rotation but I am getting error

 

Entity zig code:

namespace palet.Jig
{
    public sealed class  mod__BlockRotating : EntityJig
    {
        #region Fields

        public int mCurJigFactorNumber = 1;

        private double mRotation = 0.0;    // Factor #1

        #endregion

        #region Constructors

        public mod__BlockRotating(Entity ent)
            : base(ent)
        {
        }

        #endregion

        #region Overrides

        protected override bool Update()
        {
            switch (mCurJigFactorNumber)
            {
                case 1:
                    (Entity as BlockReference).Rotation = mRotation;
                    break;
                default:
                    return false;
            }

            return true;
        }

        protected override SamplerStatus Sampler(JigPrompts prompts)
        {
            switch (mCurJigFactorNumber)
            {
                case 1:
                    JigPromptAngleOptions prOptions1 = new JigPromptAngleOptions("\nBlock rotation angle:");
                    prOptions1.BasePoint = (Entity as BlockReference).Position;
                    prOptions1.UseBasePoint = true;
                    prOptions1.Cursor = CursorType.RubberBand;
                    PromptDoubleResult prResult1 = prompts.AcquireAngle(prOptions1);
                    if (prResult1.Status == PromptStatus.Cancel) return SamplerStatus.Cancel;

                    if (prResult1.Value.Equals(mRotation))
                    {
                        return SamplerStatus.NoChange;
                    }
                    else
                    {
                        mRotation = prResult1.Value;
                        return SamplerStatus.OK;
                    }
                default:
                    break;
            }

            return SamplerStatus.OK;
        }

        #endregion

        #region Method to Call

        public static bool Jig(BlockReference ent)
        {
            try
            {
                Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
                mod__BlockRotating jigger = new mod__BlockRotating(ent);
                PromptResult pr;
                do
                {
                    pr = ed.Drag(jigger);
                    jigger.mCurJigFactorNumber++;
                } while (pr.Status != PromptStatus.Cancel &&
                            pr.Status != PromptStatus.Error &&
                            pr.Status != PromptStatus.Keyword &&
                            jigger.mCurJigFactorNumber <= 1);

                return pr.Status == PromptStatus.OK;
            }
            catch
            {
                return false;
            }
        }


        #endregion

    }
}

 

Error That I am getting when I use the function to call jig

 System.InvalidCastException: 'Unable to cast COM object of type 'System.__ComObject' to class type 'Autodesk.AutoCAD.DatabaseServices.BlockReference'. Instances of types that represent COM components cannot be cast to types that do not represent COM components; however they can be cast to interfaces as long as the underlying COM component supports QueryInterface calls for the IID of the interface.'

 

Then I realized that  I am using 

using Autodesk.AutoCAD.Interop;
using Autodesk.AutoCAD.Interop.Common;

 AcadBlock a_BlkObj = default(AcadBlock);
 AcadBlockReference a_BlockRefObj1 = default(AcadBlockReference);
 AcadBlockReference a_BlockRefObj2 = default(AcadBlockReference);
 
 
 mod__BlockRotating.Jig((Autodesk.AutoCAD.DatabaseServices.BlockReference)a_BlockRefObj1);

 

Then I realized that I am using Autodesk.AutoCAD.Interop.Common to add the Block.. due to which its throwing error.

Now I have ported most of my code to Autodesk.AutoCAD.Interop.Common and I want to use the Entity jig to rotate some of by blocks.

Is there any resolution for this?


10 REPLIES 10
Message 2 of 11
norman.yuan
in reply to: kmkxperia

Firstly, why do you want to use COM API to create a block reference in .NET API code? It does not make much sense in most, if not all, cases.

 

Secondly, even you insist to create a COM API's AcadBlockReference and then pass it to .NET API's Jig, your code is still wrong: an instance of AcadBlockReference object cannot be created with default<T>. It can only be created by calling AcadBlock.InsertBlock() method. Once the InsertBlock() call is done, you can convert it to .NET BlockReference by DBObject.FromAcadObject() method. However, at this moment, the block reference has already been added into the database. So, if you want to jig it, you should use DrawJig, instead of EntityJig.

 

Again, I simply see no reason to create an AcadBlockReference via COM API before calling an EntityJig. You can simply:

 

using (BlockReference blockRef=new BlockReference(Point3d.Origin, [blockdefinitionId]))

{

   if (mod_BlockRotating.Jig(blockRef))

   {

      // add the blockRef to database

   }

}

Norman Yuan

Drive CAD With Code

EESignature

Message 3 of 11

The resolution is to not use the COM API unless you are exposing your API to lisp or some other automation client. 

Message 4 of 11
daniel_cadext
in reply to: kmkxperia

If you must use ActiveX, note:

AcadBlockReference is not a BlockReference

 

Look at these for casting

DBObject.FromAcadObject and DBObject.AcadObject

Python for AutoCAD, Python wrappers for ARX https://github.com/CEXT-Dan/PyRx
Message 5 of 11
kmkxperia
in reply to: norman.yuan

The Project already was developed with com APIs.. now I need to Add this new functionality to existing one.. moving all code to new will be big task .. So looking for quick solution.. 

Is there any sample code that I can study which I can refer with COM API I can use the Jig Functionality.. As I need to move, Draw and rotated the Blocks.  In below video I am not able to rotate block with cursor movement.

 

 

Message 6 of 11
norman.yuan
in reply to: kmkxperia

Well, even your .NET plugin somehow developed mostly using COM API for very odd reasons (it is .NET API plugin, isn't it? Or you would not try to do jig and post here), it does not prevent you from adding JIG using .NET API's Entity class (in your case, it is BlockReference class). So, when you only adding this jig features to your existing project, you should have no issue to do it with PURE .NET API.

 

As for your video showing the jig not working, since there is no all related code posted, all I can say is that the code of doing it is wrong.

 

Norman Yuan

Drive CAD With Code

EESignature

Message 7 of 11
kmkxperia
in reply to: norman.yuan

Hi ,

 

Below is code that I am trying after placing the block I need to Rotate the Block, Move the Block, or Draw Circle , Squre using Jig

 

 

 

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.GraphicsInterface;
using Autodesk.AutoCAD.Runtime;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Interop.Common;
using Autodesk.AutoCAD.Interop;
using System.Linq.Expressions;
using System.Windows.Forms;
using Application = Autodesk.AutoCAD.ApplicationServices.Application;
using palet.Startup;
using palet.DC;
using System.Runtime.InteropServices;
using palet.Startup.Microdesk;

namespace palet.TESTCODES
{
    public class Commands
    {
        /*public static extern int SetFocusAPI(int hwnd);
       [DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Ansi, SetLastError = true)]*/
        public static double[] dbl_Origin = new double[3];
        public static double dbl_DC_ScaleFactor = 64;

        [CommandMethod("ROTATEBLOCK")]
        public void RotateBlockCommand()
        {
            
            String s_FileName = @"XXX.dwg";
            String s_InsPrompt = "Specify insertion point of form part mark";
          

            AcadBlock a_BlkObj = default(AcadBlock);
            AcadBlockReference a_BlockRefObj1 = default(AcadBlockReference);
            AcadBlockReference a_BlockRefObj2 = default(AcadBlockReference);
            AcadLayer a_CurLayer = default(AcadLayer);
            m_ThisDrawing.acd_DocumentManager = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager;
            m_ThisDrawing.acd_AcadApplication = Autodesk.AutoCAD.ApplicationServices.Application.AcadApplication as AcadApplication;
            m_ThisDrawing.ThisDrawing = m_ThisDrawing.acd_AcadApplication.ActiveDocument;

        string cst_TempBlockName = "_Temporary";
            a_BlkObj = null;
         
            try
            {
                a_BlkObj = m_ThisDrawing.ThisDrawing.Blocks.Add(dbl_Origin, cst_TempBlockName);
                a_BlockRefObj2 = a_BlkObj.InsertBlock(dbl_Origin, s_FileName, 1, 1, 1, 0);
                a_BlockRefObj1 = m_ThisDrawing.ThisDrawing.ModelSpace.InsertBlock(dbl_Origin, a_BlkObj.Name, 1, 1, 1, fnc_dbl_UCSRotation());

                a_BlockRefObj1.ScaleEntity(dbl_Origin, dbl_DC_ScaleFactor);
                m_ThisDrawing.ThisDrawing.Utility.InitializeUserInput(1, "Undo");

                bool IsKeyword = false;
                dynamic v_IPnt = null;
                bool bln_IsManualOn = true;
               
                m_ThisDrawing.ThisDrawing.Utility.InitializeUserInput(1, "Auto");
                v_IPnt = GetPoint(Type.Missing, "\r\n" + s_InsPrompt + " or [Auto gap on]: ", ref IsKeyword);


                a_BlockRefObj1.InsertionPoint = v_IPnt;
                a_BlockRefObj1.Update();
               
                /*
                 * Till here Block is placed in the Drawing now further not sure how to proceed
                 * I need to Rotate the Block, Move the Block, Draw Circle , Squre using Jig
                 */

                //RotateBlockJig(v_IPnt);

                /* Rotaton Jig,  should happen here
                 * Should take angle of rotaion and rotate the block accordingly
                 * This is place where  I am not able to proceed.. 
                 */




            }
            catch { 
            
            }


        }

        public static dynamic GetPoint(object Point, object Prompt, ref bool IsKeyword)
        {
            object Ret = null;
            try
            {
                if (ReferenceEquals(Point, null))
                {
                    Point = Type.Missing;
                }
                Ret = m_ThisDrawing.ThisDrawing.Utility.GetPoint(Point, Prompt);
               
            }
            catch (COMException ComEx)
            {
                if (ComEx.Message.IndexOf("User input is a keyword", StringComparison.InvariantCultureIgnoreCase) != -1)
                {
                   
                    IsKeyword = true;
                }
                else
                {
                    
                    Ret = null;
                    if (ComEx.HResult == -2147352567)
                    {
                      
                    }
                    else
                    {
                       
                    }

                }
            }
            catch (System.Exception ex)
            {
                Ret = null;
           
            }
            return Ret;
        }

        public static double fnc_dbl_UCSRotation()
        {
            object v_XVector = null;
            double d_UCSRotation = 0;
            try
            {
                v_XVector = m_ThisDrawing.ThisDrawing.GetVariable("UCSXDIR");
                d_UCSRotation = System.Convert.ToDouble(m_ThisDrawing.ThisDrawing.Utility.AngleFromXAxis(dbl_Origin, v_XVector));
            }
            catch (System.Exception)
            {
                d_UCSRotation = 0;
            }
            return d_UCSRotation;
        }


    }

    public class RotateBlockJig : EntityJig
    {
        private Point3d _center;
        private double _angle;

        public RotateBlockJig(Point3d center)
            : base(new BlockReference(center, ObjectId.Null))
        {
            _center = center;
            _angle = 0.0;
        }

        protected override SamplerStatus Sampler(JigPrompts prompts)
        {
            JigPromptAngleOptions angleOptions = new JigPromptAngleOptions("\nSelect rotation angle:");
            angleOptions.DefaultValue = _angle;
            PromptDoubleResult angleResult = prompts.AcquireAngle(angleOptions);

            if (angleResult.Status == PromptStatus.OK)
            {
                _angle = angleResult.Value;
                return SamplerStatus.OK;
            }

            return SamplerStatus.Cancel;
        }

        protected override bool Update()
        {
            // Rotate the block reference
            ((BlockReference)Entity).TransformBy(Matrix3d.Rotation(_angle, Vector3d.ZAxis, _center));
            return true;
        }

    }


       public class m_ThisDrawing
    {
       
        public static DocumentCollection acd_DocumentManager;
        public static AcadApplication acd_AcadApplication;
        public static AcadDocument ThisDrawing;

        
    }

}

 

 

 





Message 8 of 11
norman.yuan
in reply to: kmkxperia

Which IDE you use to write the code? VisualStudio? Dosen't Visual Studio prompt code error with red underline, does it? The code certainly cannot be compiled. 

 

Just to begin with:

a_BlkObj = m_ThisDrawing.ThisDrawing.Blocks.Add(dbl_Origin, cst_TempBlockName);
                a_BlockRefObj2 = a_BlkObj.InsertBlock(dbl_Origin, s_FileName, 1, 1, 1, 0);
                a_BlockRefObj1 = m_ThisDrawing.ThisDrawing.ModelSpace.InsertBlock(dbl_Origin, a_BlkObj.Name, 1, 1, 1, fnc_dbl_UCSRotation());

The first line is completely wrong: ThisDrawing in your code is an .NET API Document, not an AcadDocument in COM API.

 

In your previous post, you mention that the .NET plugin mainly uses COM API. However, if the code shown here is for that plugin, I do not see why stick with COM API (a VBA porting project, maybe?) and I'd restart/learn from scratch with real .NET API plugin. It would be waste of time rewrite COM API code in .NET API plugin.

 

I'd strongly suggest you start with learning basic AutoCAD .NET APIs. I also strongly suggest that you REMOVE the reference to COM API interop assembly and do/learn writing code with AutoCAD .NET API, so that you can do thing correctly.

 

If you still insist in using COM API to insert a block, you need to learn how to obtain an AcadApplication/AcadDocument from .NET Application/Document:

 

AcadApplicatio comApp=(AcadDocument)Application.AcadApplication;

AcadDocument comDoc=(AcadDocument)Application.DocumentManager.MdiActiveDocument.GetAcadDocument();

 

Then you can go on with COM API operation. Again, in most cases, it is not necessary, and probably bad move.

 

 

 

Norman Yuan

Drive CAD With Code

EESignature

Message 9 of 11
kmkxperia
in reply to: norman.yuan

m_ThisDrawing is the class at end of code which refers for AcadDocument using Autodesk.AutoCAD.Interop;
your suggesion seems good to move to new .net API.. but as I already said its big application which need this change. Moving all code to .net  compatible API is not possible. 


public class m_ThisDrawing
    {
       
        public static DocumentCollection acd_DocumentManager;
        public static AcadApplication acd_AcadApplication;
        public static AcadDocument ThisDrawing;

        
    }

 

Message 10 of 11
norman.yuan
in reply to: kmkxperia

OK, I overlooked. But still, the code would not work: it added a block definition with no entities in it. So, when the AcadModelSpace.InsertBlock() is called, there is nothing can be seen/scaled/rotated as AcadBlockReference - it is an empty block reference.

 

Let's put this aside, assuming the code is only meant to show how an AcadBlockReference is created. Then you want to jig-rotate an EXISTING block reference. so, here is what you can do:

 

1. You should use DrawJig, instead of EntityJig. Because EntityJig is meant to jig an new Entity (not database-residing yet). In case the user cancels the jig, the entity should be disposed and only when the jig is Oked, the entity is then added into the database.  For DrawJig, you pass an Entity opened for writing in a transaction to the jig. If the jig is OKed, the jig calling code comitted the transaction; if cancelled, the calling code abort the transaction. Technically, you can use Entity jig for existing entity, but it is not EntityJig intended for;

 

2. For jigging an existing AcadBlockReference, you could do something like:

 

private void JigAcdBlockReference(AcadBlockReference acadBlkRef)
{
	using (var tran = [database].TransactionManager.StartTransaction())
	{
		BlockReference blkref=DBObject.FromAcadObject(acadBlkRef) as BlockReference
        
		if (blkRef==null) 
        {
			throw new ArgumentException("Wrong AcadObject!");
		}
        if (!blkRef.IsWriteEnabled)
		{
			blkRef.UpgradeOpen();
		}
        var ok = mod_BlockRotating.Jig(blkRef);
		if (ok)
			tran.Commit()
		else
			tran.Abort();
	}
}

public class mod_BlockRotatingJig : DrawJig
{
    private readonly BlockReference _blk;
	public mod_RlockRotaingJig(BlockReference blk):base()
    {
		_blk= blk;
    }
    // implement virtual methods here
}

 

 

Norman Yuan

Drive CAD With Code

EESignature

Message 11 of 11
kmkxperia
in reply to: kmkxperia

Thanks will try this out

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Forma Design Contest


AutoCAD Beta