TheSwamp

Code Red => .NET => Topic started by: Kerry on June 12, 2010, 08:43:01 AM

Title: PInvoke acdbEntUpd
Post by: Kerry on June 12, 2010, 08:43:01 AM
I'm brain dead and need a hand please.

I'm trying to achieve an Update on a Single entity.
The testbed is a little contrived, but you should get the idea ( I hope )
I've tried to code it to show the returns ...

Here's the issue :
After selecting an entity the acdbEntUpd() returns RTERROR (-5001 )
and an ERRNO of 5

My head hurts and I'm going to bed with the hope that the programming fairies solve this overnight  :-D


Comments are in-line

Code: [Select]
[assembly: CommandClass(typeof(KdubTesting.TestCommands))]

namespace KdubTesting
{
    // CodeHimBelongaKdub ©  Jun 2008
    public partial class Kdub_API
    {
        //====================================================================================
        [DllImport("acad.exe", CallingConvention = CallingConvention.Cdecl)]
        public static extern int acdbEntUpd(Int64 adsName);
        //====================================================================================
        /*
          Acad::ErrorStatus acdbGetAdsName(
                ads_name& objName,
                AcDbObjectId obj
          );
          This function fills in objName with the ads_name that corresponds to the objId object ID.
          Returns Acad::eOk if successful. If objId is 0, then Acad::eNullObjectId is returned.
       */
        [DllImport("acdb18.dll", CallingConvention = CallingConvention.Cdecl,
        EntryPoint = "?acdbGetAdsName@@YA?AW4ErrorStatus@Acad@@AAY01JVAcDbObjectId@@@Z")]
        public extern static ErrorStatus acdbGetAdsName(out Int64 objName, ObjectId objId );
        //====================================================================================

    }
    // CodeHimBelongaKdub ©  Jun 2008
    public partial class TestCommands
    {
        [CommandMethod("EntUpd")]
        static public void TestacdbEntUpd()
        {
            Document doc = AcadApp.DocumentManager.MdiActiveDocument;
            Editor ed = doc.Editor;
            Database db = doc.Database;
  
            PromptEntityResult res = ed.GetEntity("\nSelect an entity to Regen:");
            ObjectId id = res.ObjectId;
            Int64 adsName;
            ErrorStatus es;            

            using(Transaction tr = db.TransactionManager.StartTransaction())
            {
                es = Kdub_API.acdbGetAdsName(out adsName, id);

                ed.WriteMessage("\n adsName is {0} ", adsName);
                ed.WriteMessage("\n ErrorStatus is {0} ", es);

                int apiReturn = Kdub_API.acdbEntUpd(adsName);
                /*
                 * If acdbEntUpd() succeeds, it returns RTNORM  ( 5100 )
                 * otherwise,                it returns RTERROR.(-5001 )
                 * When acdbEntUpd() fails, it sets the system variable ERRNO
                 * to a value that indicates the reason for the failure.
                 */

                ed.WriteMessage("\n api acdbEntUpd_Return is {0} ", apiReturn);
                ed.WriteMessage("\n System variable ERRNO  is {0} ", AcadApp.GetSystemVariable("ERRNO"));

                /*
                 * Returns
                 * Command: EntUpd
                 *Select an entity to Regen:
                 *
                 * adsName is 8793785127955584200
                 * ErrorStatus is OK
                 * api acdbEntUpd_Return is -5001
                 * System variable ERRNO  is 5
                 */
                tr.Commit();
            }
        }
    }
}        
Title: Re: PInvoke acdbEntUpd
Post by: Bryco on June 12, 2010, 10:56:13 AM
You're going to hate this.
Change all from int64 to long
 adsName is 9179526903997960920
 ErrorStatus is OK
 api acdbEntUpd_Return is 4294962295
 System variable ERRNO  is 5
Title: Re: PInvoke acdbEntUpd
Post by: Kerry on June 12, 2010, 05:49:23 PM

Thanks for looking Bryce.
I'll grab a coffee and start again. :)

Title: Re: PInvoke acdbEntUpd
Post by: Kerry on June 12, 2010, 06:16:36 PM
NoteThe possible values of ERRNO, and their meanings, are subject to change.
Online program error codes
 
Value
  Meaning
 
0
 No error
 
1
 Invalid symbol table name
 
2
 Invalid entity or selection set name
 
3
 Exceeded maximum number of selection sets
 
4
 Invalid selection set
 
5
 Improper use of block definition
6
 Improper use of xref
 
7
 Object selection: pick failed
 
8
 End of entity file
 
9
 End of block definition file
 
10
 Failed to find last entity
 
//=======================================


Title: Re: PInvoke acdbEntUpd
Post by: Kerry on June 12, 2010, 06:46:42 PM
Bryce,
a long and an Int64 are the same thing  64bit signed integer
'long' is just an alias for Int64.

In fact, if we right-click on 'long' and select 'GoToDefinition' the definitionsig' is
    // Summary:
    //     Represents a 64-bit signed integer.
    [Serializable]
    [ComVisible(true)]
    public struct Int64 : IComparable, IFormattable, IConvertible, IComparable<long>, IEquatable<long>
    { //................


//--------------------------------------------------

another clue :
The acdbEntUpd generates an ERRNO of 5
When the routine returns to AutoCAD, the ERRNO command from the commandLine reports 2.



Quote
Command: errno
Enter new value for ERRNO <0>:

Command: entupd

Select an entity to Regen:
 adsName is 9158139860942894088
 ErrorStatus is OK
 api acdbEntUpd_Return is -5001
 System variable ERRNO  is 5
 Complete: System variable ERRNO  is 5

Command: errno
Enter new value for ERRNO <2>:
Title: Re: PInvoke acdbEntUpd
Post by: Kerry on June 12, 2010, 07:12:19 PM

The 'Scrambled' name for acdbGetAdsName is the same in acdb17.dll 32bit  and acdb18.dll 32bit ... so my DllImports should be suitable for AC 2007-AC2011 ( once I get the bug sorted. )
Title: Re: PInvoke acdbEntUpd
Post by: jgr on June 12, 2010, 07:30:27 PM
Sorry, i don't undertand, but try:
acdbEntUpd(ObjectId adsName)

I think  adsname = objectid
Title: Re: PInvoke acdbEntUpd
Post by: Kerry on June 12, 2010, 07:52:02 PM
Thanks for looking

Perhaps it should.
I tried that first and got the same error, so tried the acdbGetAdsName()

ie : using
        [DllImport("acad.exe", CallingConvention = CallingConvention.Cdecl)]
        //public static extern int acdbEntUpd(long adsName);
        public static extern int acdbEntUpd(ObjectId objId);

and
int apiReturn = Kdub_API.acdbEntUpd(id);

I get
Command: entupd

Select an entity to Regen:
 api acdbEntUpd_Return is -5001
 System variable ERRNO  is 5
 Complete: System variable ERRNO  is 5
[added]
BUT errno at the commandLine is 0 now as it should be :)
Title: Re: PInvoke acdbEntUpd
Post by: LE3 on June 12, 2010, 07:54:21 PM
See if this works (learned from the masters).

Code: [Select]
       // ARX signature:
        // int acdbEntUpd( const ads_name ent);
        [DllImport(ACAD_EXE, CallingConvention = CallingConvention.Cdecl, EntryPoint = "acdbEntUpd")]
        public static extern int acdbEntUpd ( long[] ent );

        // ARX signature:
        // Acad::ErrorStatus acdbGetAdsName(ads_name& objName, AcDbObjectId objId);
        [DllImport("acdb18.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "?acdbGetAdsName@@YA?AW4ErrorStatus@Acad@@AAY01JVAcDbObjectId@@@Z")]
        public static extern int acdbGetAdsName ( long[] objName, ObjectId objId );

        [CommandMethod("TEST1")]
        static public void CmdTest ( )
        {
            Document doc = AcadApp.DocumentManager.MdiActiveDocument;
            Editor ed = doc.Editor;

            PromptEntityResult per = ed.GetEntity("\nSelect object: ");
            if (per.Status != PromptStatus.OK) return;
            long[] objName = new long[] { 0, 0 };
            PInvoke.acdbGetAdsName(objName, per.ObjectId);
            PInvoke.acdbEntUpd(objName);
        }
Title: Re: PInvoke acdbEntUpd
Post by: Kerry on June 12, 2010, 08:08:53 PM

Thanks Luis, I'll have a look shortly

Do you know why an array of longs is used as a parameter ??
Title: Re: PInvoke acdbEntUpd
Post by: Kerry on June 12, 2010, 08:11:08 PM

I take it from the use of ACAD_EXE that the code is from Tony .. I've noticed that he uses a constant of that name to represent "acad.exe"
Title: Re: PInvoke acdbEntUpd
Post by: LE3 on June 12, 2010, 08:30:41 PM

Thanks Luis, I'll have a look shortly

Do you know why an array of longs is used as a parameter ??


because of this:
typedef long ads_name[2];  (under arxdef.chm a2008 and adsdef.h)
Title: Re: PInvoke acdbEntUpd
Post by: LE3 on June 12, 2010, 08:31:19 PM

I take it from the use of ACAD_EXE that the code is from Tony .. I've noticed that he uses a constant of that name to represent "acad.exe"
yep, learned that style from him :)
Title: Re: PInvoke acdbEntUpd
Post by: Kerry on June 12, 2010, 08:44:04 PM
Thanks Luis

One more:
Why are you using PInvoke.xxxxx ??

Did you have those DLLImport definitions in a  PInvoke class at one stage ??
Title: Re: PInvoke acdbEntUpd
Post by: Kerry on June 12, 2010, 08:47:28 PM
Seems to work fine .. need to do a bit more testing ..

the call to acdbEntUpd returns  5100 (ie RTNORM ) which is good :)

Thanks.
Title: Re: PInvoke acdbEntUpd
Post by: Kerry on June 12, 2010, 08:49:01 PM

Thanks Luis, I'll have a look shortly

Do you know why an array of longs is used as a parameter ??


because of this:
typedef long ads_name[2];  (under arxdef.chm a2008 and adsdef.h)


ahhh .. makes sense  :-)
Title: Re: PInvoke acdbEntUpd
Post by: LE3 on June 12, 2010, 08:52:52 PM
I started to use a home made PInvoke class (and for my own arx exported functions), and depending on the needs I add that on my new projects.
Sorry, I know I use that, but was easy for me to do the quick test here.


Thanks Luis

One more:
Why are you using PInvoke.xxxxx ??

Did you have those DLLImport definitions in a  PInvoke class at one stage ??
Title: Re: PInvoke acdbEntUpd
Post by: LE3 on June 12, 2010, 08:59:26 PM
ahhh .. makes sense  :-)
And do not why this info is not on the latest arxref help (at least per my findings in the ARX sdk 2010)
Title: Re: PInvoke acdbEntUpd
Post by: Kerry on June 12, 2010, 08:59:40 PM
Thanks, I do the same thing .. API's in their own class.

thought is would be the case :-)
Title: Re: PInvoke acdbEntUpd
Post by: pkohut on June 12, 2010, 09:23:57 PM
if ObjectId in the .Net world == AcDbObjectId in the C++ world, then ads_name != ObjectId.

You have to use the .Net equivalent of these C++ API's
acdbGetObjectId(AcDbObjectId & objId, ads_name objName)  or
acdbGetAdsName(ads_name & objName, AcDbObjectId objId) to go the other way around.

Under the covers ads_name is 2 32 bit longs in 32 bit Autocad and 2 64 bit longs in 64 bit acad.
Up to 2007,
Code: [Select]
typedef long     ads_name[2];2008+,
Code: [Select]
#ifndef _WIN64
typedef __w64 long ads_name[2];
typedef __w64 long *ads_namep;
#else
typedef __int64 ads_name[2];
typedef __int64 *ads_namep;
#endif

(mental juggling here, about how TT's code would work)
But that really doesn't matter since the 128 bit ads_name of .Net will comfortably fit the 64 bit ads_name of 32 bit Acad, so they are compatible.
Title: Re: PInvoke acdbEntUpd
Post by: Kerry on June 12, 2010, 09:26:25 PM

because of this:
typedef long ads_name[2];  (under arxdef.chm a2008 and adsdef.h)

I don't have a arxdef.chm ; assume you mean arxref.chm, which I was using

I'm using AC2011.
The ads_name is defined in adsdef.h as you say,
and described in the arxdev.chm ... which I hadn't looked at  :oops:

Thanks Luis.
Title: Re: PInvoke acdbEntUpd
Post by: Kerry on June 12, 2010, 09:31:58 PM
if ObjectId in the .Net world == AcDbObjectId in the C++ world, then ads_name != ObjectId.

You have to use the .Net equivalent of these C++ API's
acdbGetObjectId(AcDbObjectId & objId, ads_name objName)  or
acdbGetAdsName(ads_name & objName, AcDbObjectId objId) to go the other way around.

< .. >

Thanks Paul
That clarifies jgr's comment and confirms the translation.

I really mucked up the array of longs for ads_name  :oops:

Thanks for posting.
Title: Re: PInvoke acdbEntUpd
Post by: pkohut on June 12, 2010, 09:32:40 PM
arxdev.chm ... which I hadn't looked at  :oops:

Type "ads_name" in arxdev.chm and check out "about" and "exchanging with AcDbObjectId's".
Title: Re: PInvoke acdbEntUpd
Post by: LE3 on June 12, 2010, 09:40:13 PM
Yikes... need another glasses :ugly: 
Yes, did not look into arxdev, normally I always use arxref...

I don't have a arxdef.chm ; assume you mean arxref.chm, which I was using

I'm using AC2011.
The ads_name is defined in adsdef.h as you say,
and described in the arxdev.chm ... which I hadn't looked at  :oops:

Thanks Luis.
Title: Re: PInvoke acdbEntUpd
Post by: LE3 on June 12, 2010, 09:42:40 PM
(mental juggling here, about how TT's code would work)

Which one?
Title: Re: PInvoke acdbEntUpd
Post by: Kerry on June 12, 2010, 10:16:06 PM


Thanks guys .. it's been an illuminating couple of hours  :-)
Title: Re: PInvoke acdbEntUpd
Post by: Kerry on June 13, 2010, 05:38:40 AM

Quote from: Tony T adng
I think this is what you would use:

static extern int acdbEntUpd( out Int64 ename );

Something else to test :)
Title: Re: PInvoke acdbEntUpd
Post by: LE3 on June 13, 2010, 11:37:03 AM
Did you tried Kerry?
Don't understand the out in there... the arx signature does not return the ads_name.... now I am confuse.
Now, I am going for my first coffee...


It works.

Another trick of Tony's bag of tricks... good


Quote from: Tony T adng
I think this is what you would use:

static extern int acdbEntUpd( out Int64 ename );

Something else to test :)

Title: Re: PInvoke acdbEntUpd
Post by: Kerry on June 13, 2010, 11:01:55 PM

At the moment I'm quite happy with this test
... that may change , of course :)

Code: [Select]

[assembly: CommandClass(typeof(KdubTesting.TestCommands))]

namespace KdubTesting
{
    // CodeHimBelongaKdub Jun 2008
    public partial class TestCommands
    {
        const string ACAD_EXE = "Acad.exe";
        const short RTNORM = 5100;
        const short RTERROR = -5001;
        //===================================================================================
        // ARX signature:
        // Acad::ErrorStatus acdbGetAdsName(ads_name& objName, AcDbObjectId objId);
        [DllImport("acdb18.dll", CallingConvention = CallingConvention.Cdecl,
            EntryPoint = "?acdbGetAdsName@@YA?AW4ErrorStatus@Acad@@AAY01JVAcDbObjectId@@@Z")]
        public static extern ErrorStatus acdbGetAdsName(out long adsName, ObjectId id);
        /*
        * Parameters
        *  ads_name& objName    Output ads_name 
        *  AcDbObjectId objId   Input object ID 
        *
        * This function fills in objName with the ads_name that
        * corresponds to the objId object ID.
        * Returns Acad::eOk if successful.
        * If objId is 0, then Acad::eNullObjectId is returned.
        */
        //===================================================================================
        // ARX signature:
        // int acdbEntUpd( const ads_name ent);
        [DllImport(ACAD_EXE, CallingConvention = CallingConvention.Cdecl,
            EntryPoint = "acdbEntUpd")]
        public static extern int acdbEntUpd(out long adsName);
        /*
        * If acdbEntUpd() succeeds, it returns RTNORM  ( 5100 )
        * otherwise,                it returns RTERROR.(-5001 )
        * When acdbEntUpd() fails, it sets the system variable ERRNO to a value
        * that indicates the reason for the failure.
        */
        //===================================================================================
        [CommandMethod("Test0614a")]
        static public void Test0614a_acdbEntUpd_withInt64()
        {
            Document doc = AcadApp.DocumentManager.MdiActiveDocument;
            Editor ed = doc.Editor;

            PromptEntityResult per = ed.GetEntity("\nSelect object: ");
            if(per.Status != PromptStatus.OK)
            {
                ed.WriteMessage("\n Nothing Selected");
                return;
            }

            ObjectId id = per.ObjectId;
            long adsName ;
            ErrorStatus es = acdbGetAdsName(out adsName, id);
            if(es != ErrorStatus.OK)
            {
                System.Windows.Forms.MessageBox.Show(
                    String.Format("ErrorStatus is: {0} \nCancelling Routine.", es),
                    "acdbGetAdsName ErrorStatus failure");
                return;
            }

            int api_Result = acdbEntUpd(out adsName);
            if(api_Result != RTNORM)
            {
                System.Windows.Forms.MessageBox.Show(
                   String.Format("ERRNO is : {0} \nCancelling Routine.",
                   AcadApp.GetSystemVariable("ERRNO")),
                   "acdbEntUpd api_Result failure");
                return;
            }
            //------------
            ed.WriteMessage("\n ObjectId is {0} ", id);
            ed.WriteMessage("\n adsName is {0} ", adsName);
            ed.WriteMessage("\n api acdbEntUpd_Result is {0} ", api_Result);
            ed.WriteMessage("\n System variable ERRNO  is {0} ",
                         AcadApp.GetSystemVariable("ERRNO"));
        }
    }
}
Title: Re: PInvoke acdbEntUpd
Post by: Kerry on June 13, 2010, 11:10:50 PM

... however, something like this may be a little more practical.
I'd be happy to have someone seriously test it.
see file attached for includes.

Code: [Select]
[assembly: CommandClass(typeof(KdubTesting.TestCommands))]

namespace KdubTesting
{
    // CodeHimBelongaKdub Jun 2008
    public partial class TestCommands
    {
        const string ACAD_EXE = "Acad.exe";
        const short RTNORM = 5100;
        const short RTERROR = -5001;
        //===================================================================================
        // ARX signature:
        // Acad::ErrorStatus acdbGetAdsName(ads_name& objName, AcDbObjectId objId);
        [DllImport("acdb18.dll", CallingConvention = CallingConvention.Cdecl,
            EntryPoint = "?acdbGetAdsName@@YA?AW4ErrorStatus@Acad@@AAY01JVAcDbObjectId@@@Z")]
        public static extern ErrorStatus acdbGetAdsName(out long adsName, ObjectId id);
        /*
        * Parameters
        *  ads_name& objName    Output ads_name  
        *  AcDbObjectId objId   Input object ID  
        *
        * This function fills in objName with the ads_name that
        * corresponds to the objId object ID.
        * Returns Acad::eOk if successful.
        * If objId is 0, then Acad::eNullObjectId is returned.
        */
        //===================================================================================
        // ARX signature:
        // int acdbEntUpd( const ads_name ent);
        [DllImport(ACAD_EXE, CallingConvention = CallingConvention.Cdecl,
            EntryPoint = "acdbEntUpd")]
        public static extern int acdbEntUpd(out long adsName);
        /*
        * If acdbEntUpd() succeeds, it returns RTNORM  ( 5100 )
        * otherwise,                it returns RTERROR.(-5001 )
        * When acdbEntUpd() fails, it sets the system variable ERRNO to a value
        * that indicates the reason for the failure.
        */
        //===================================================================================
        //===================================================================================
        [CommandMethod("Test0614b")]
        static public void Test0614b_acdbEntUpd_withBoolTestMethod()
        {
            Document doc = AcadApp.DocumentManager.MdiActiveDocument;
            Editor ed = doc.Editor;

            PromptEntityResult per = ed.GetEntity("\nSelect object: ");
            if(per.Status != PromptStatus.OK)
            {
                ed.WriteMessage("\n Nothing Selected");
                return;
            }
            ObjectId id = per.ObjectId;
            if( EntityUpdate(id))
                System.Windows.Forms.MessageBox.Show( "Entity Updates sucessfully", "Test0614b");
            else
                System.Windows.Forms.MessageBox.Show( "It hit the fan", "Test0614b");
        }
        //===================================================================================
        public static bool EntityUpdate(ObjectId id)
        {
            long adsName;
            if(acdbGetAdsName(out adsName, id) != ErrorStatus.OK)
                return false;
            return (acdbEntUpd(out adsName) == RTNORM);
        }
        //===================================================================================
     }
}

Quote
References
//AcCui :
//acdbmgd :
//acdbmgdbrep :
//AcDx :
//acmgd :
//AcMr :
//AcTcMgd :
//AcWindows :
//AdWindows :
//System :
//System.Core :
//System.Data :
//System.Windows.Forms :
//System.Xml&comref:
//Autodesk.AutoCAD.Interop
//Autodesk.AutoCAD.Interop.Common  
//stdole                        
//mscorlib

Title: Re: PInvoke acdbEntUpd
Post by: Jeff_M on March 06, 2016, 04:52:32 PM
Kerry, sorry to dig up this old thread but I've just had an occasion to find a way to update a single object. My Google search led me here. After a bit of work to change your last solution to work in Acad2014 or 2015, it runs without error but also doesn't update the entity.

Background for my needs....I've been coding for Civil3d 2016 lately. I found that I have some tools to edit Aecc objects, but they were not updating until a REGEN was issued. I didn't want to add a full REGEN due to these drawings usually being fairly large and a regen is often a bit slow. In 2016 that isn't a problem, because I found the Acad.Utils.RegenEntity() method which updates the objects just as I needed. But then I opened the projects for C3D2014 & 2015 (we don't support any of the older versions with new code) and was greeted with the old RegenEntity() not found error. Hit Google looking for something I could do, found this thread and it's sister over on the Autodesk .NET forum.

So, back to my current issue with this code. It seems like it should do what I need, but it is not updating the entities like the 2016 RegenEntity() method does. I also tried Tony's mention of changing the entity's layer to the same layer, which also doesn't update the object. Did this work to update objects for you?
Title: Re: PInvoke acdbEntUpd
Post by: Jeff_M on March 06, 2016, 06:08:49 PM
Well, I stumbled upon a solution for the older versions that was too easy....just toggle the entity's Visible property off then back on, entity updates perfectly.
Title: Re: PInvoke acdbEntUpd
Post by: kdub_nz on March 06, 2016, 09:44:22 PM
Well, I stumbled upon a solution for the older versions that was too easy....just toggle the entity's Visible property off then back on, entity updates perfectly.

great !

Title: Re: PInvoke acdbEntUpd
Post by: kdub_nz on March 06, 2016, 10:04:32 PM
< .. > In 2016 that isn't a problem, because I found the Acad.Utils.RegenEntity() method which updates the objects just as I needed. < .. >

Give them another 10 years, they may produce a (nearly) complete API :)
Title: Re: PInvoke acdbEntUpd
Post by: Jeff H on March 06, 2016, 11:59:57 PM
< .. > In 2016 that isn't a problem, because I found the Acad.Utils.RegenEntity() method which updates the objects just as I needed. < .. >
If you need it in 2015 looks like you can pinvoke acdbQueueForRegen

RegenEntity()
Code: [Select]
public static unsafe void RegenEntity(ObjectId entId)
{
    AcDbObjectId id;
    *((long*) &id) = 0L;
    *((long*) &id) = entId.OldIdPtr.ToInt64();
    acdbQueueForRegen((AcDbObjectId modopt(IsConst)*) &id, 1);
}

 
Title: Re: PInvoke acdbEntUpd
Post by: MexicanCustard on March 07, 2016, 07:42:45 AM
< .. > In 2016 that isn't a problem, because I found the Acad.Utils.RegenEntity() method which updates the objects just as I needed. < .. >

Give them another 10 years, they may produce a (nearly) complete API :)


I doubt it.
Title: Re: PInvoke acdbEntUpd
Post by: Jeff_M on March 07, 2016, 12:31:11 PM

If you need it in 2015 looks like you can pinvoke acdbQueueForRegen

RegenEntity()
Code: [Select]
public static unsafe void RegenEntity(ObjectId entId)
{
    AcDbObjectId id;
    *((long*) &id) = 0L;
    *((long*) &id) = entId.OldIdPtr.ToInt64();
    acdbQueueForRegen((AcDbObjectId modopt(IsConst)*) &id, 1);
}

 
Yes, Jeff, I found that as well. Passing just the ObjectId did nothing, passing the ObjectId and 1 crashed Autocad (could be I was not implementing it correctly). That's when I kept looking for something else and found a post that mentioned the Visible property could be a solution.