Author Topic: adding/deleting block attributes  (Read 21555 times)

0 Members and 1 Guest are viewing this topic.

shsss1985

  • Guest
adding/deleting block attributes
« on: July 10, 2012, 10:24:03 PM »
Hello everyone!
I have block with attributes , which have some values.
I need to add one or more attributes in this block, but values of existing attributes must be saved.
The same for deleting.
i am using ACAD2012 (objectARX 2012).

Thanks.

MexicanCustard

  • Swamp Rat
  • Posts: 705
Re: adding/deleting block attributes
« Reply #1 on: July 11, 2012, 07:18:56 AM »
Code: [Select]
//To add a new AttributeDefintion to an existing block
Database db = Application.DocumentManager.MDIActiveDocument.Database;

using (Transaction tr = db.TransactionManager.StartTransaction())
{
    var ad = new AttributeDefinition();
    ad.SetDatabaseDefaults(db);
    ad.Tag = "YOUR_TAG";
    ad.Prompt = "Your Prompt";

    var bt = db.BlockTableId.GetObject(OpenMode:ForRead);
    var btr = bt["SOMEBLOCK"].GetObject(OpenMode:ForWrite);
    btr.AppendEntity(ad);
    tr.AddNewlyCreatedDBObject(ad, true);

    tr.Commit();
}

Revit 2019, AMEP 2019 64bit Win 10

fixo

  • Guest
Re: adding/deleting block attributes
« Reply #2 on: July 11, 2012, 03:49:18 PM »
Here is my 2 cents
Change the block name and attribute tag

Code - C#: [Select]
  1.        [CommandMethod("dewa")]
  2.         public static void DelAttribute()
  3.         {
  4.             Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
  5.  
  6.             Database db = doc.Database;
  7.  
  8.             Editor ed = doc.Editor;
  9.  
  10.             using (Transaction tr = db.TransactionManager.StartTransaction())
  11.             {
  12.                 BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead, false);
  13.  
  14.                 if (!bt.Has("IMP"))
  15.                 {
  16.                     ed.WriteMessage("\nBlock definition IMP does not  exist");
  17.                     return;
  18.                 }
  19.  
  20.                 BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt["IMP"], OpenMode.ForRead, false);
  21.  
  22.                 AttributeDefinition foundDef = new AttributeDefinition();
  23.  
  24.                 foreach (ObjectId id in btr)
  25.                 {
  26.                     DBObject obj = (DBObject)tr.GetObject(id, OpenMode.ForRead, false);
  27.  
  28.                     AttributeDefinition attDef = obj as AttributeDefinition;
  29.  
  30.                     if ((attDef != null) && (!attDef.Constant))
  31.                     {
  32.  
  33.                         if (attDef.Tag == "METRIC")
  34.                         {
  35.                             foundDef = attDef;
  36.  
  37.                             //break;
  38.                         }
  39.  
  40.  
  41.                         bt.UpgradeOpen();
  42.  
  43.                         btr.UpgradeOpen();
  44.  
  45.                         foundDef.UpgradeOpen();
  46.  
  47.                         foundDef.Erase();
  48.  
  49.                         btr.DowngradeOpen();
  50.  
  51.                         bt.DowngradeOpen();
  52.  
  53.                     }
  54.  
  55.  
  56.                 }
  57.  
  58.                 tr.Commit();
  59.  
  60.                 ed.WriteMessage("\nPerform command \"ATTSYNC\" manually");
  61.             }
  62.         }
  63.  
  64.         [CommandMethod("newa")]
  65.         public static void AddNewAtt()
  66.         {
  67.  
  68.             Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
  69.             Database db = doc.Database;
  70.             Editor ed = doc.Editor;
  71.             using (Transaction tr = db.TransactionManager.StartTransaction())
  72.             {
  73.                 BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead, false);
  74.  
  75.                 if (!bt.Has("PART"))
  76.                 {
  77.                     ed.WriteMessage("\nBlock definition PART does not  exist");
  78.                     return;
  79.                 }
  80.  
  81.                 BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt["PART"], OpenMode.ForRead, false);
  82.  
  83.                 // location of the AttributeDefinition in the
  84.  
  85.                 // block definition
  86.  
  87.                 Point3d ptloc = new Point3d(0, 2, 0);
  88.                 // create a AttributeDefinition
  89.                 // specify the text,tag and prompt
  90.  
  91.                 string strvalue = "NEW VALUE ADDED";
  92.  
  93.                 string strtag = "MYTAG";
  94.  
  95.                 string strprompt = "Enter a new value";
  96.                 // used current text style
  97.                 AttributeDefinition attDef = new AttributeDefinition(ptloc, strvalue, strtag, strprompt, db.Textstyle);
  98.                 attDef.Height = 0.12;
  99.                 attDef.Layer = "0";
  100.                 attDef.Color = Autodesk.AutoCAD.Colors.Color.FromColorIndex(ColorMethod.ByAci, 0);
  101.                 attDef.LinetypeId = db.ContinuousLinetype;
  102.                 // append the AttributeDefinition to the definition
  103.                 btr.UpgradeOpen();
  104.                 btr.AppendEntity(attDef);
  105.                 tr.AddNewlyCreatedDBObject(attDef, true);
  106.                 btr.DowngradeOpen();
  107.                 tr.Commit();
  108.             }
  109.         }

edit->kdub code formatting
« Last Edit: July 13, 2012, 03:05:47 AM by Kerry »

shsss1985

  • Guest
Re: adding/deleting block attributes
« Reply #3 on: July 12, 2012, 12:00:38 AM »
thx MexicanCustard it works!
Fixo, the adding procedure is working, thx! But delete attribute isnt working(
i make a little changes, but it show me an error.
Code - C#: [Select]
  1. public void delAttribute(string blockName, string delTagName)
  2.         {
  3.             Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
  4.             Autodesk.AutoCAD.DatabaseServices.Database db = doc.Database;
  5.             Editor ed = doc.Editor;
  6.             try
  7.             {
  8.                 using (doc.LockDocument())
  9.                 {
  10.                     using (Transaction tr = db.TransactionManager.StartTransaction())
  11.                     {
  12.                         BlockTable bt = (BlockTable)(tr.GetObject(db.BlockTableId, OpenMode.ForRead, false));
  13.                         BlockTableRecord btr = (BlockTableRecord)(tr.GetObject(bt[blockName], OpenMode.ForRead, false));
  14.                         AttributeDefinition foundedDef = new AttributeDefinition();
  15.                         foreach (ObjectId id in btr)
  16.                         {
  17.                             DBObject obj = (DBObject)tr.GetObject(id, OpenMode.ForRead, false);
  18.                             AttributeDefinition attDef = obj as AttributeDefinition;
  19.                             if ((attDef != null) && (!attDef.Constant))
  20.                             {
  21.                                 if (attDef.Tag == delTagName)
  22.                                     foundedDef = attDef;
  23.                             }
  24.                             ////bt.UpgradeOpen();
  25.                             ////btr.UpgradeOpen();
  26.                             //foundedDef.UpgradeOpen();
  27.                             foundedDef.Erase();
  28.                             //btr.DowngradeOpen();
  29.                             //bt.DowngradeOpen();
  30.                         }
  31.                         tr.Commit();
  32.                     }
  33.                 }
  34.             }
  35.             catch (System.Exception ex)
  36.             {
  37.                 MessageBox.Show("Error: "+ ex.Message);
  38.             }
  39.            
  40.         }
the error is:  eNoDatabase


edit->kdub code formatting code = csharp.
« Last Edit: July 13, 2012, 03:03:32 AM by Kerry »

fixo

  • Guest
Re: adding/deleting block attributes
« Reply #4 on: July 12, 2012, 01:06:32 AM »
Sorry but I've deleted an attribute from block with no problems on my machine,
I'm using A2010,

~'J'~

Delegate

  • Guest
Re: adding/deleting block attributes
« Reply #5 on: July 12, 2012, 04:52:42 AM »
Is it because you have commented out the foundedref.upgradeopen()?

shsss1985

  • Guest
Re: adding/deleting block attributes
« Reply #6 on: July 13, 2012, 02:14:11 AM »
No, i dont think so. If i uncomment this command there is another error: eWasOpenForWrite.
i really dont understand why this happened.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: adding/deleting block attributes
« Reply #7 on: July 13, 2012, 03:01:24 AM »

I can't test the code at the moment but it may help if you are a bit more explicit about where the exception is and the actual exception bessage ...

Regards
kdub
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

shsss1985

  • Guest
Re: adding/deleting block attributes
« Reply #8 on: July 13, 2012, 04:30:23 AM »
Thx, Kerry, i'll try to explain.
Code - C#: [Select]
  1. public void delAttribute(string blockName, string delTagName)
  2.         {
  3.             Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
  4.             Autodesk.AutoCAD.DatabaseServices.Database db = doc.Database;
  5.             Editor ed = doc.Editor;
  6.             try
  7.             {
  8.                 using (doc.LockDocument())
  9.                 {
  10.                     using (Transaction tr = db.TransactionManager.StartTransaction())
  11.                     {
  12.                         BlockTable bt = (BlockTable)(tr.GetObject(db.BlockTableId, OpenMode.ForRead, false));
  13.                         BlockTableRecord btr = (BlockTableRecord)(tr.GetObject(bt[blockName], OpenMode.ForRead, false));
  14.                         AttributeDefinition foundedDef = new AttributeDefinition();
  15.                         foreach (ObjectId id in btr)
  16.                         {
  17.                             DBObject obj = (DBObject)tr.GetObject(id, OpenMode.ForRead, false);
  18.                             AttributeDefinition attDef = obj as AttributeDefinition;
  19.                             if ((attDef != null) && (!attDef.Constant))
  20.                             {
  21.                                 if (attDef.Tag == delTagName)
  22.                                     foundedDef = attDef;
  23.                             }
  24.                             bt.UpgradeOpen();
  25.                             btr.UpgradeOpen();
  26.                             foundedDef.UpgradeOpen();
  27.                             foundedDef.Erase();
  28.                            
  29.                         }
  30.                         tr.Commit();
  31.                     }
  32.                 }
  33.             }
  34.             catch (Autodesk.AutoCAD.Runtime.Exception ex)
  35.             {
  36.                 MessageBox.Show("Error: " + ex.ErrorStatus);
  37.             }
  38.            
  39.         }
  40.  
if debug this code, everything works. Except on step
 
Code: [Select]

...
foundedDef.UpgradeOpen();
foundedDef.Erase();
...
 

after that i have error : eWasOpenForWrite

if i am commenting foundedDef.UpgradeOpen();
then i have an error: eNoDatabase, it is really strange because i connect to db = doc.Database


edit->kdub code formatting code = csharp.
« Last Edit: July 13, 2012, 04:35:46 AM by Kerry »

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: adding/deleting block attributes
« Reply #9 on: July 13, 2012, 04:42:23 AM »
Hi,

You're trying to upgrade and erase founDef at each loop (even when founDef didn't change)
Try with :

Code - C#: [Select]
  1. foreach (ObjectId id in btr)
  2. {
  3.     DBObject obj = (DBObject)tr.GetObject(id, OpenMode.ForRead, false) as AttributeDefinition;
  4.     if (attDef != null && !attDef.Constant && attDef.Tag == delTagName)
  5.     {
  6.         attDef.UpgradeOpen();
  7.         attDef.Erase();
  8.         break; // break the loop as the attribute is found
  9.     }
  10.  }
« Last Edit: July 13, 2012, 04:47:02 AM by gile »
Speaking English as a French Frog

shsss1985

  • Guest
Re: adding/deleting block attributes
« Reply #10 on: July 13, 2012, 04:52:54 AM »
oh yes it works! it really my bad!!!
Thx, gile, that pointed out an error!

cadplayer

  • Bull Frog
  • Posts: 390
  • Autocad Civil3d, OpenDCL.Runtime, LISP, .NET (C#)
Re: adding/deleting block attributes
« Reply #11 on: January 30, 2013, 06:18:32 AM »
Maybe it´s for a beginner a lot of stuff but I´m really intressting how the hole code looks like and works Can you show them ?
The thing is I try it to do with Lisp without _attsync. But without sucsess. So is it possible with c#.NET add Attributes without regenerate the block /Dirk
« Last Edit: January 30, 2013, 06:37:28 AM by cadplayer »

WILL HATCH

  • Bull Frog
  • Posts: 450
Re: adding/deleting block attributes
« Reply #12 on: January 30, 2013, 11:30:26 AM »
I took a slightly different approach to dealing with this issue.  To use this routine create an attribute definition in the drawing and position it relative to the block reference you wish to append it to.  Select the attribute definition, then the block reference and it will add the attribute definition to the block definition and then add an attribute reference to every instance of the block. The key to not requiring ATTSYNC is the foreach statement (line 31) where the attribute reference is added to each block reference.  Let me know if you need this extended to work with dynamic blocks.

Code - C#: [Select]
  1. [CommandMethod("AppendAttribute")]
  2.         public void AppendAttribute()
  3.         {
  4.             Document doc = Application.DocumentManager.MdiActiveDocument;
  5.             Editor ed = doc.Editor;
  6.             Database db = doc.Database;
  7.             PromptEntityOptions peo = new PromptEntityOptions("\nSelect attribute to add");
  8.             peo.SetRejectMessage("\nNot an AttributeDefinition");
  9.             peo.AddAllowedClass(typeof(AttributeDefinition), true);
  10.             PromptEntityResult per = ed.GetEntity(peo);
  11.             if (per.Status != PromptStatus.OK) return;
  12.             ObjectId adId = per.ObjectId;
  13.             peo = new PromptEntityOptions("\nSelect block to append attribute");
  14.             peo.SetRejectMessage("\nNot a BlockReference");
  15.             peo.AddAllowedClass(typeof(BlockReference), true);
  16.             per = ed.GetEntity(peo);
  17.             if (per.Status != PromptStatus.OK) return;
  18.             ObjectId brId = per.ObjectId;
  19.             using (Transaction tr = db.TransactionManager.StartTransaction())
  20.             {
  21.                 try
  22.                 {
  23.                     AttributeDefinition ad = (AttributeDefinition)tr.GetObject(adId, OpenMode.ForWrite);
  24.                     BlockReference br = (BlockReference)tr.GetObject(brId, OpenMode.ForRead);
  25.                     BlockTableRecord btr = (BlockTableRecord)tr.GetObject(br.BlockTableRecord, OpenMode.ForWrite);
  26.                     AttributeDefinition NEWad = (AttributeDefinition)ad.Clone();
  27.                     NEWad.TransformBy(br.BlockTransform.Inverse()); //to set the AD to the BTR coordinate system
  28.                     ObjectId NEWadId = btr.AppendEntity(NEWad);
  29.                     tr.AddNewlyCreatedDBObject(NEWad, true);
  30.                     ObjectIdCollection blockIds = btr.GetBlockReferenceIds(true, true);
  31.                     foreach (ObjectId id in blockIds) //add attribute reference to all blocks
  32.                     {
  33.                         br = (BlockReference)tr.GetObject(id, OpenMode.ForWrite);
  34.                         AttributeReference ar = new AttributeReference();
  35.                         ar.SetAttributeFromBlock(NEWad, br.BlockTransform);
  36.                         ar.TextString = ad.TextString;
  37.                         br.AttributeCollection.AppendAttribute(ar);
  38.                         tr.AddNewlyCreatedDBObject(ar, true);
  39.                     }
  40.                     ad.Erase();
  41.                     tr.Commit();
  42.  
  43.                 }
  44.                 catch (System.Exception e)
  45.                 {
  46.                     ed.WriteMessage("\nError: {0}\n{1}", e.Message, e.StackTrace);
  47.                 }
  48.             }
  49.            
  50.         }
  51.  

Below is similar, deletes an attribute reference from a block definition and all associated block references without going into the block editor.

Code - C#: [Select]
  1.         [CommandMethod("EraseAttribute")]
  2.         public void EraseAttribute()
  3.         {
  4.             Document doc = Application.DocumentManager.MdiActiveDocument;
  5.             Editor ed = doc.Editor;
  6.             Database db = doc.Database;
  7.             PromptNestedEntityOptions pneo = new PromptNestedEntityOptions("\nSelect attribute to erase");
  8.             using (Transaction tr = db.TransactionManager.StartTransaction())
  9.             {
  10.                 try
  11.                 {
  12.                     ObjectId arId;
  13.                     while (true)
  14.                     {
  15.                         PromptEntityResult per = ed.GetNestedEntity(pneo);
  16.                         if (per.Status != PromptStatus.OK) return;
  17.                         arId = per.ObjectId;
  18.                         if (tr.GetObject(arId, OpenMode.ForRead).GetType() == typeof(AttributeReference))
  19.                             break;
  20.                         ed.WriteMessage("\nNot an AttributeReference");
  21.                     }
  22.                     AttributeReference ar = (AttributeReference)tr.GetObject(arId, OpenMode.ForWrite);
  23.                     BlockReference br = (BlockReference)tr.GetObject(ar.OwnerId, OpenMode.ForRead);
  24.                     BlockTableRecord btr = (BlockTableRecord)tr.GetObject(br.BlockTableRecord, OpenMode.ForWrite);
  25.                     foreach (ObjectId id in btr)
  26.                     {
  27.                         AttributeDefinition ad = tr.GetObject(id, OpenMode.ForRead) as AttributeDefinition;
  28.                         if (ad == null)
  29.                             continue;
  30.                         if (ad.Tag != ar.Tag)
  31.                             continue;
  32.                         ad.UpgradeOpen();
  33.                         ad.Erase();
  34.                     }
  35.                     foreach (ObjectId id in btr.GetBlockReferenceIds(true, true))
  36.                     {
  37.                         br = (BlockReference)tr.GetObject(id, OpenMode.ForWrite);
  38.                         foreach (ObjectId attId in br.AttributeCollection)
  39.                         {
  40.                             AttributeReference att = (AttributeReference)tr.GetObject(attId, OpenMode.ForWrite);
  41.                             if (att.Tag == ar.Tag)
  42.                             {
  43.                                 att.Erase();
  44.                             }
  45.                         }
  46.                     }
  47.                     tr.Commit();
  48.                 }
  49.                 catch (System.Exception e)
  50.                 {
  51.                     ed.WriteMessage("\nError: {0}\n{1}", e.Message, e.StackTrace);
  52.                 }
  53.             }
  54.         }
  55.  
« Last Edit: January 30, 2013, 11:59:30 AM by WILL HATCH »

kaefer

  • Guest
Re: adding/deleting block attributes
« Reply #13 on: January 30, 2013, 01:32:35 PM »
Let me know if you need this extended to work with dynamic blocks.

Dynamic blocks aside, you'll need probably a call to AttributeReference.AdjustAlignment(Database) somewhere to take care of alignments other than AttachmentPoint.BaseLeft. Then there should be a special case to support multi-line attributes, by testing for IsMTextAttribute/IsMTextAttributeDefinition and calling UpdateMTextAttribute().

Andrey did a recursive Attsync for .Net, with source code here.

Jeff H

  • Needs a day job
  • Posts: 6150
Re: adding/deleting block attributes
« Reply #14 on: January 30, 2013, 01:39:17 PM »
Here is another way Tony shows using AcDbMatchProperties protocol extension.

WILL HATCH

  • Bull Frog
  • Posts: 450
Re: adding/deleting block attributes
« Reply #15 on: January 30, 2013, 03:37:34 PM »
Let me know if you need this extended to work with dynamic blocks.

Dynamic blocks aside, you'll need probably a call to AttributeReference.AdjustAlignment(Database) somewhere to take care of alignments other than AttachmentPoint.BaseLeft. Then there should be a special case to support multi-line attributes, by testing for IsMTextAttribute/IsMTextAttributeDefinition and calling UpdateMTextAttribute().

Andrey did a recursive Attsync for .Net, with source code here.

This code has been tested in both cases of non standard alignment and mtext attributes and it functions properly.  I remember reading somewhere that the special cases require special support, do you suppose there is something in here that autocad is handling for me? I'm using autocad 2012

Cheers

kaefer

  • Guest
Re: adding/deleting block attributes
« Reply #16 on: January 30, 2013, 04:31:03 PM »
This code has been tested in both cases of non standard alignment and mtext attributes and it functions properly.  I remember reading somewhere that the special cases require special support, do you suppose there is something in here that autocad is handling for me?

If all you're doing is calling SetAttributeFromBlock(), yes, likely it is. I'm thinking that it may be necessary in case anybody fiddles with properties of the new attribute reference.

Just goes to show that I failed to read your code thoroughly. It must have looked just somehow incomplete.

Possible other areas of concern: Did you test with constant attribute definitions? Shouldn't you dispose the cloned attribute definition under all circumstances; in fact, even doing the same with the new attribute reference too?

WILL HATCH

  • Bull Frog
  • Posts: 450
Re: adding/deleting block attributes
« Reply #17 on: January 30, 2013, 06:06:22 PM »
Thank you kaefer! The criticism is appreciated! I have never used a constant attribute so didn't think to handle that case separately.  Turns out a constant attribute does NOT get an attribute reference, so the foreach section of my code needs to be skipped, and a regen must be executed to display the new text.  This complicates the ERASEATTRIBUTE method now, as I filter for an attribute reference... I'll think about how to fix that issue.

Code - C#: [Select]
  1. try
  2.                 {
  3.                     AttributeDefinition ad = (AttributeDefinition)tr.GetObject(adId, OpenMode.ForWrite);
  4.                     BlockReference br = (BlockReference)tr.GetObject(brId, OpenMode.ForRead);
  5.                     BlockTableRecord btr = (BlockTableRecord)tr.GetObject(br.BlockTableRecord, OpenMode.ForWrite);
  6.                     AttributeDefinition NEWad = (AttributeDefinition)ad.Clone();
  7.                     NEWad.TransformBy(br.BlockTransform.Inverse()); //to set the AD to the BTR coordinate system
  8.                     ObjectId NEWadId = btr.AppendEntity(NEWad);
  9.                     tr.AddNewlyCreatedDBObject(NEWad, true);
  10.                     ObjectIdCollection blockIds = btr.GetBlockReferenceIds(true, true);
  11.                     if (!NEWad.Constant) //constant attributes are NOT added to the block reference
  12.                         foreach (ObjectId id in blockIds) //add attribute reference to all blocks
  13.                         {
  14.                             br = (BlockReference)tr.GetObject(id, OpenMode.ForWrite);
  15.                             AttributeReference ar = new AttributeReference();
  16.                             ar.SetAttributeFromBlock(NEWad, br.BlockTransform);
  17.                             ar.TextString = ad.TextString;
  18.                             br.AttributeCollection.AppendAttribute(ar);
  19.                             tr.AddNewlyCreatedDBObject(ar, true);
  20.                         }
  21.                     ad.Erase();
  22.                     tr.Commit();
  23.                     ed.Regen();//Regen needed for constant attribute to correctly display
  24.                 }
  25.  

Please correct me if I'm understanding this incorrectly or if I'm losing performance in this method:

-The cloned attribute definition (ad) and the new def (NEWad) get disposed as we leave the scope of the try block (along with br, btr, NEWadId, blockIds etc)
-the attribute reference (ar) gets disposed each time we complete a cycle in the foreach loop

Since this all happens via the garbage collector it's actually being delayed as long as the system does not have an immediate need to reclaim the memory, making the program function slightly faster for the operator.

If anybody can find a way to break this program I'd appreciate it!

Cheers

WILL HATCH

  • Bull Frog
  • Posts: 450
Re: adding/deleting block attributes
« Reply #18 on: January 30, 2013, 06:35:44 PM »
Modified the ERASEATTRIBUTE method to handle constant attributes, turns out they are still just a nested AttributeDefinition

Code - C#: [Select]
  1.                 try
  2.                 {
  3.                     ObjectId arId;
  4.                     System.Type objType;
  5.                     while (true)
  6.                     {
  7.                         PromptEntityResult per = ed.GetNestedEntity(pneo);
  8.                         if (per.Status != PromptStatus.OK) return;
  9.                         arId = per.ObjectId;
  10.                         objType = tr.GetObject(arId, OpenMode.ForRead).GetType();
  11.                         if ((objType == typeof(AttributeReference))|(objType == typeof(AttributeDefinition)))
  12.                             break;
  13.                         ed.WriteMessage("\nNot an Attribute");
  14.                     }
  15.                     if (objType == typeof(AttributeReference))
  16.                     {
  17.                         AttributeReference ar = (AttributeReference)tr.GetObject(arId, OpenMode.ForWrite);
  18.                         BlockReference br = (BlockReference)tr.GetObject(ar.OwnerId, OpenMode.ForRead);
  19.                         BlockTableRecord btr = (BlockTableRecord)tr.GetObject(br.BlockTableRecord, OpenMode.ForWrite);
  20.                         foreach (ObjectId id in btr)
  21.                         {
  22.                             AttributeDefinition ad = tr.GetObject(id, OpenMode.ForRead) as AttributeDefinition;
  23.                             if (ad == null)
  24.                                 continue;
  25.                             if (ad.Tag != ar.Tag)
  26.                                 continue;
  27.                             ad.UpgradeOpen();
  28.                             ad.Erase();
  29.                         }
  30.                         foreach (ObjectId id in btr.GetBlockReferenceIds(true, true))
  31.                         {
  32.                             br = (BlockReference)tr.GetObject(id, OpenMode.ForWrite);
  33.                             foreach (ObjectId attId in br.AttributeCollection)
  34.                             {
  35.                                 AttributeReference att = (AttributeReference)tr.GetObject(attId, OpenMode.ForWrite);
  36.                                 if (att.Tag == ar.Tag)
  37.                                 {
  38.                                     att.Erase();
  39.                                 }
  40.                             }
  41.                         }
  42.                     }
  43.                     else
  44.                     {
  45.                         AttributeDefinition att = (AttributeDefinition)tr.GetObject(arId, OpenMode.ForWrite);
  46.                         att.Erase();
  47.                         ed.Regen();
  48.                     }
  49.                     tr.Commit();
  50.                 }
  51.  

This little routine was helpful with investigating what type the nested entity was (as you cant just view its properties  :-()

Code - C#: [Select]
  1.         [CommandMethod("gettype")]
  2.         public void getType()
  3.         {
  4.             Document doc = Application.DocumentManager.MdiActiveDocument;
  5.             Editor ed = doc.Editor;
  6.             Database db = doc.Database;
  7.             PromptNestedEntityOptions pneo = new PromptNestedEntityOptions("\nSelect nested object to get type");
  8.             PromptEntityResult per = ed.GetNestedEntity(pneo);
  9.             if (per.Status != PromptStatus.OK) return;
  10.             using (Transaction tr = db.TransactionManager.StartTransaction())
  11.             {
  12.                 ed.WriteMessage("\nType of object is: {0}", tr.GetObject(per.ObjectId, OpenMode.ForRead).GetType());
  13.             }
  14.         }

Thanks again for pointing that issue out kaefer!

Cheers

Jeff H

  • Needs a day job
  • Posts: 6150
Re: adding/deleting block attributes
« Reply #19 on: January 30, 2013, 06:37:46 PM »
-The cloned attribute definition (ad) and the new def (NEWad) get disposed as we leave the scope of the try block (along with br, btr, NEWadId, blockIds etc)
-the attribute reference (ar) gets disposed each time we complete a cycle in the foreach loop

I think they have disposed called on them during the execution of Transaction.Commit()

btr is known to the transaction because it is opened with the transaction
(ObjectId.GetObject, Transaction.GetObject, .. in the end call TransactionManager.GetObject())

ar & NEWad are also disposed through the TransactionManager and are made known with AddNewlyCreatedDBObject()
If an error occurred after creation of (ar),(NEWad) but before  tr.AddNewlyCreatedDBObject() then there would be a leak in your example.

WILL HATCH

  • Bull Frog
  • Posts: 450
Re: adding/deleting block attributes
« Reply #20 on: January 30, 2013, 08:20:19 PM »
-The cloned attribute definition (ad) and the new def (NEWad) get disposed as we leave the scope of the try block (along with br, btr, NEWadId, blockIds etc)
-the attribute reference (ar) gets disposed each time we complete a cycle in the foreach loop

I think they have disposed called on them during the execution of Transaction.Commit()

btr is known to the transaction because it is opened with the transaction
(ObjectId.GetObject, Transaction.GetObject, .. in the end call TransactionManager.GetObject())

ar & NEWad are also disposed through the TransactionManager and are made known with AddNewlyCreatedDBObject()
If an error occurred after creation of (ar),(NEWad) but before  tr.AddNewlyCreatedDBObject() then there would be a leak in your example.

I've added a couple modifications to my code to show that tr.Commit() is not disposing these objects, and used them afterwards to show that they are still completely usable afterwards:

Code - C#: [Select]
  1.         [CommandMethod("TransactionTesting")]
  2.         public void TestTransaction()
  3.         {
  4.             Document doc = Application.DocumentManager.MdiActiveDocument;
  5.             Editor ed = doc.Editor;
  6.             Database db = doc.Database;
  7.             PromptEntityOptions peo = new PromptEntityOptions("\nSelect attribute to add");
  8.             peo.SetRejectMessage("\nNot an AttributeDefinition");
  9.             peo.AddAllowedClass(typeof(AttributeDefinition), true);
  10.             PromptEntityResult per = ed.GetEntity(peo);
  11.             if (per.Status != PromptStatus.OK) return;
  12.             ObjectId adId = per.ObjectId;
  13.             peo = new PromptEntityOptions("\nSelect block to append attribute");
  14.             peo.SetRejectMessage("\nNot a BlockReference");
  15.             peo.AddAllowedClass(typeof(BlockReference), true);
  16.             per = ed.GetEntity(peo);
  17.             if (per.Status != PromptStatus.OK) return;
  18.             ObjectId brId = per.ObjectId;
  19.             AttributeDefinition ad = null;
  20.             BlockReference br = null;
  21.             using (Transaction tr = db.TransactionManager.StartTransaction())
  22.             {
  23.                 try
  24.                 {
  25.                     AttributeDefinition ad1 = (AttributeDefinition)tr.GetObject(adId, OpenMode.ForWrite);
  26.                     BlockReference br1 = (BlockReference)tr.GetObject(brId, OpenMode.ForRead);
  27.                     tr.Commit();
  28.                     ad = ad1;//will fail if disposed at tr.commit()
  29.                     br = br1;
  30.                 }
  31.                 catch (System.Exception e)
  32.                 {
  33.                     ed.WriteMessage("\nError: {0}\n{1}", e.Message, e.StackTrace);
  34.                 }
  35.             }
  36.             using (Transaction tr = db.TransactionManager.StartTransaction())
  37.             {
  38.                 try
  39.                 {
  40.                    
  41.                     BlockTableRecord btr = (BlockTableRecord)tr.GetObject(br.BlockTableRecord, OpenMode.ForWrite);
  42.                     AttributeDefinition NEWad = (AttributeDefinition)ad.Clone();
  43.                     NEWad.TransformBy(br.BlockTransform.Inverse()); //to set the AD to the BTR coordinate system
  44.                     ObjectId NEWadId = btr.AppendEntity(NEWad);
  45.                     tr.AddNewlyCreatedDBObject(NEWad, true);
  46.                     ObjectIdCollection blockIds = btr.GetBlockReferenceIds(true, true);
  47.                     if (!NEWad.Constant) //constant attributes are NOT added to the block reference
  48.                         foreach (ObjectId id in blockIds) //add attribute reference to all blocks
  49.                         {
  50.                             br = (BlockReference)tr.GetObject(id, OpenMode.ForWrite);
  51.                             AttributeReference ar = new AttributeReference();
  52.                             ar.SetAttributeFromBlock(NEWad, br.BlockTransform);
  53.                             ar.TextString = ad.TextString;
  54.                             br.AttributeCollection.AppendAttribute(ar);
  55.                             tr.AddNewlyCreatedDBObject(ar, true);
  56.                         }
  57.                     ad.Erase();
  58.                     tr.Commit();
  59.                     ed.Regen();//Regen needed for constant attribute to correctly display
  60.                 }
  61.                 catch (System.Exception e)
  62.                 {
  63.                     ed.WriteMessage("\nError: {0}\n{1}", e.Message, e.StackTrace);
  64.                 }
  65.             }
  66.             BlockReference br2 = (BlockReference)br.Clone();//cloning outside of a transaction works
  67.             using (Transaction tr = db.TransactionManager.StartTransaction())
  68.             {
  69.                
  70.                 AttributeDefinition ad1 = new AttributeDefinition();
  71.                 ad1.SetDatabaseDefaults();
  72.                 ad1.Tag = "tag";
  73.                 ad1.TextString = "textString";
  74.                 ad1.Constant = true;
  75.                 Matrix3d mat = br2.BlockTransform;
  76.                 ad1.TransformBy(mat);
  77.                 BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
  78.                 btr.AppendEntity(ad1);
  79.                 tr.AddNewlyCreatedDBObject(ad1, true);
  80.                tr.Commit();
  81.                 ed.Regen();
  82.             }
  83.         }
  84.  

Jeff H

  • Needs a day job
  • Posts: 6150
Re: adding/deleting block attributes
« Reply #21 on: January 30, 2013, 10:20:59 PM »

********************************EDIT************************
On second look I am not sure I thought clone was working because using GetObject was setting autodelete to false and the UmanagedObject was not getting
set to IntPtr.Zero, but I don't know and would have to look into it futher.
********************************EDIT************************



I guess the question is what does disposed mean?
I meant dispose has been called on the managed wrapper and the native object has been closed( AcDbObject.close)
During Commit() is probably not correct, but when the transaction is closed or if its nested when topmost transaction is closed.

Quote
ad = ad1;//will fail if disposed at tr.commit()
Assigning ad = ad1 should work fine as long as ad1 and ad are compatible types.
 
So when i said disposed I meant Dispose() implemented by IDisposable has been called.

When calling clone
Code - C#: [Select]
  1.  
  2. public virtual unsafe object Clone()
  3. {
  4.     AcRxObject* impObj = this.GetImpObj();
  5.     IntPtr unmanagedPointer = new IntPtr((void*) **(((long*) impObj))[0x10L](impObj));
  6.     return Create(unmanagedPointer, true);
  7. }
  8.  

The (IntPtr)UnmanagedObject property was still valid to create a new managed wrapper.


Are you not getting an error at ad.Erase()?

« Last Edit: January 30, 2013, 10:38:03 PM by Jeff H »

WILL HATCH

  • Bull Frog
  • Posts: 450
Re: adding/deleting block attributes
« Reply #22 on: January 30, 2013, 11:15:18 PM »
Nope, no errors. As far as I can tell since the objects are resident to a database present in ram the managed class still holds the pointer to them. Unless we call dispose manually I think they'll live till the garbage collector cleans up.  There are no errors provided we don't attempt to perform operations that must be transaction resident.
Cheers

cadplayer

  • Bull Frog
  • Posts: 390
  • Autocad Civil3d, OpenDCL.Runtime, LISP, .NET (C#)
Re: adding/deleting block attributes
« Reply #23 on: January 31, 2013, 03:49:36 AM »
Thanks boys fantastic work! /Dirk

Hugo

  • Bull Frog
  • Posts: 430
Re: adding/deleting block attributes
« Reply #24 on: January 31, 2013, 07:46:14 AM »
What should I shop here

Was muss ich hier Laden

Quote
Der Typ- oder Namespacename "Matrix3d" konnte nicht gefunden werden. (Fehlt eine Using-Direktive oder ein Assemblyverweis?)

Danke

WILL HATCH

  • Bull Frog
  • Posts: 450
Re: adding/deleting block attributes
« Reply #25 on: January 31, 2013, 09:42:13 AM »
Die Matrix3D in Autodesk.Autocad.Geometry Namespace enthalten. Es ist in der Regel recht einfach durch googeln Autocad Matrix3D (oder eine andere Klasse, die Sie kann gesucht werden) finden Namespace
 Erhalten auch die ARX-Dokumentation und den Namespace aller Klassen werden zusammen mit all ihren Methoden gezeigt. Sie haben eine einfachere Zeit bekommen Antworten, wenn Sie Ihre Kommentare übersetzen ...
Prost

Hugo

  • Bull Frog
  • Posts: 430
Re: adding/deleting block attributes
« Reply #26 on: February 01, 2013, 12:06:22 AM »
now I get this error message

jetzt bekomme ich diese Fehlermeldung


Jeff H

  • Needs a day job
  • Posts: 6150
Re: adding/deleting block attributes
« Reply #27 on: February 01, 2013, 12:55:55 AM »
Probably at ad.Erase() since it gets closed when the first transaction ends.


 

Hugo

  • Bull Frog
  • Posts: 430
Re: adding/deleting block attributes
« Reply #28 on: February 01, 2013, 02:10:08 AM »
Hello Jeff H

The wahrs now it works great 1000 times thanks  :-) :-) :-)


Hallo Jeff H

Das wahrs jetzt funktioniert es, super 1000 mal Danke


Now would be even great for ATTSYNC a program without moving the attributes.
Jetzt wäre noch toll ein  Programm für ATTSYNC ohne die Attribute zu verschieben.
« Last Edit: February 01, 2013, 02:32:36 AM by Hugo »

WILL HATCH

  • Bull Frog
  • Posts: 450
Re: adding/deleting block attributes
« Reply #29 on: February 01, 2013, 10:45:43 AM »
Hugo, Jeff,

What version are you using?  I'm trying to wrap my head around why things are working here if they object is apparently closed with the transaction  :-o.  If this is something version dependent then my code will be failing on different versions of AutoCAD... I can see how it would make logical sense that as the transaction was disposed the objects opened for write would be downgraded to read only to prevent any modification later.  Can anybody explain what is going on here?

Cheers

Jeff H

  • Needs a day job
  • Posts: 6150
Re: adding/deleting block attributes
« Reply #30 on: February 01, 2013, 12:01:22 PM »
Here is the exact code with a couple of additions I tried.


-Added a event handler for ObjectClosed.
-Added after first Transaction

                ed.WriteMessage("\n" + ad.UnmanagedObject.ToString());
                ed.WriteMessage("\n" + ad.IsDisposed.ToString());
                ed.WriteMessage("\n" + ad.Tag);
                //ad.LockPositionInBlock = true;///// Boom


Notice how checking IsDisposed works because just checking managed wrappers properties
Code - C#: [Select]
  1.  
  2. public bool IsDisposed
  3. {
  4.     [return: MarshalAs(UnmanagedType.U1)]
  5.     get
  6.     {
  7.         GC.KeepAlive(this);
  8.         return (this.m_imp == IntPtr.Zero);
  9.     }
  10. }
  11.  


Checking its Tag property works.
AcDbAttribute::tag
Quote
This function returns a pointer to a copy of the tag string for the attribute. The tag string is the identifier you see if you explode the AcDbBlockReference that owns the attribute, so that the attribute reverts back to the AcDbAttributeDefinition that was part of the original reference's block definition.
The caller of this function is responsible for deallocating the memory used by the returned string. The acutDelString() global function should be used for this purpose.
The tag string is used for DXF group code 2.


Notice it is just using the Intptr for its address to marshal back a string.
Code - C#: [Select]
  1.  
  2.     get
  3.     {
  4.         char* chPtr = 0L;
  5.         try
  6.         {
  7.             chPtr = AcDbAttribute.tag((AcDbAttribute modopt(IsConst)* modopt(IsConst) modopt(IsConst)) this.GetImpObj());
  8.             return WcharToString((char modopt(IsConst)*) chPtr);
  9.         }
  10.         finally
  11.         {
  12.             acutDelBuffer((void** modopt(IsImplicitlyDereferenced)) &chPtr);
  13.         }
  14.         return null;
  15.     }
  16.  
  17.  
  18.  


Now ad.LockPositionInBlock will go boom since it tries to modify the object.


The line ad.Erase is where it goes booms but can be fixed with adding
tr.GetObject(ad.ObjectId, OpenMode.ForWrite); or ad.ObjectId.Open()


The word Dispose gets used and thrown around alot and usually is understood as releasing unmanaged memory, but I think it is a big NoNo to delete a object in ObjectARX and just call Close because they keep the objects in memory.
So it might better to think of Dispose and Transactions as just opening and closing objects instead of memory management.


So from what I can tell is Clone and other methods work because they just use the address(GetImpObj, DisposableWrapper.UnmanagedObject) to go get some information and marshal it back to you.


Erase is trying to modify an object and there is where I get a BOOM!


Also the ObjectClosed event fires for me during Commit as the code below shows some message boxes.


Code - C#: [Select]
  1.  
  2.         [CommandMethod("TransactionTesting")]
  3.         public void TestTransaction()
  4.         {
  5.             try
  6.             {
  7.                 Document doc = Application.DocumentManager.MdiActiveDocument;
  8.                 Editor ed = doc.Editor;
  9.                 Database db = doc.Database;
  10.                 PromptEntityOptions peo = new PromptEntityOptions("\nSelect attribute to add");
  11.                 peo.SetRejectMessage("\nNot an AttributeDefinition");
  12.                 peo.AddAllowedClass(typeof(AttributeDefinition), true);
  13.                 PromptEntityResult per = ed.GetEntity(peo);
  14.                 if (per.Status != PromptStatus.OK) return;
  15.                 ObjectId adId = per.ObjectId;
  16.                 peo = new PromptEntityOptions("\nSelect block to append attribute");
  17.                 peo.SetRejectMessage("\nNot a BlockReference");
  18.                 peo.AddAllowedClass(typeof(BlockReference), true);
  19.                 per = ed.GetEntity(peo);
  20.                 if (per.Status != PromptStatus.OK) return;
  21.                 ObjectId brId = per.ObjectId;
  22.                 AttributeDefinition ad = null;
  23.                 BlockReference br = null;
  24.                 using (Transaction tr = db.TransactionManager.StartTransaction())
  25.                 {
  26.                     try
  27.                     {
  28.                         AttributeDefinition ad1 = (AttributeDefinition)tr.GetObject(adId, OpenMode.ForWrite);
  29.                         ad1.ObjectClosed += ad1_ObjectClosed;
  30.                         BlockReference br1 = (BlockReference)tr.GetObject(brId, OpenMode.ForRead);
  31.                         Application.ShowAlertDialog("Before Commit");
  32.                         tr.Commit();
  33.                         Application.ShowAlertDialog("After Commit");
  34.                         ad = ad1;//will fail if disposed at tr.commit()
  35.                         br = br1;
  36.                     }
  37.                     catch (System.Exception e)
  38.                     {
  39.                         ed.WriteMessage("\nError: {0}\n{1}", e.Message, e.StackTrace);
  40.                     }
  41.                     Application.ShowAlertDialog("Before Transaction Closed");
  42.                 }
  43.                 Application.ShowAlertDialog("After Transaction Closed");
  44.                 ed.WriteMessage("\n" + ad.UnmanagedObject.ToString());
  45.                 ed.WriteMessage("\n" + ad.IsDisposed.ToString());
  46.                 ed.WriteMessage("\n" + ad.Tag);
  47.                 //ad.LockPositionInBlock = true;///// Boom
  48.                 using (Transaction tr = db.TransactionManager.StartTransaction())
  49.                 {
  50.                     try
  51.                     {
  52.  
  53.  
  54.                         BlockTableRecord btr = (BlockTableRecord)tr.GetObject(br.BlockTableRecord, OpenMode.ForWrite);
  55.                         AttributeDefinition NEWad = (AttributeDefinition)ad.Clone();
  56.                         NEWad.TransformBy(br.BlockTransform.Inverse()); //to set the AD to the BTR coordinate system
  57.                         ObjectId NEWadId = btr.AppendEntity(NEWad);
  58.                         tr.AddNewlyCreatedDBObject(NEWad, true);
  59.                         ObjectIdCollection blockIds = btr.GetBlockReferenceIds(true, true);
  60.                         if (!NEWad.Constant) //constant attributes are NOT added to the block reference
  61.                             foreach (ObjectId id in blockIds) //add attribute reference to all blocks
  62.                             {
  63.                                 br = (BlockReference)tr.GetObject(id, OpenMode.ForWrite);
  64.                                 AttributeReference ar = new AttributeReference();
  65.                                 ar.SetAttributeFromBlock(NEWad, br.BlockTransform);
  66.                                 ar.TextString = ad.TextString;
  67.                                 br.AttributeCollection.AppendAttribute(ar);
  68.                                 tr.AddNewlyCreatedDBObject(ar, true);
  69.                             }
  70.                         tr.GetObject(ad.ObjectId, OpenMode.ForWrite);//////Commit line out and Boom
  71.                         ad.Erase();//////Will only work if above line is commented out
  72.                         tr.Commit();
  73.                         ed.Regen();//Regen needed for constant attribute to correctly display
  74.                     }
  75.                     catch (Autodesk.AutoCAD.Runtime.Exception ex)
  76.                     {
  77.                         if (ex.ErrorStatus != ErrorStatus.NotOpenForWrite)
  78.                         {
  79.                             ed.WriteMessage("\nError: {0}\n{1}", ex.GetBaseException(), ex.StackTrace);
  80.                         }
  81.                         throw;
  82.                     }
  83.                 }
  84.                 BlockReference br2 = (BlockReference)br.Clone();//cloning outside of a transaction works
  85.                 using (Transaction tr = db.TransactionManager.StartTransaction())
  86.                 {
  87.  
  88.  
  89.                     AttributeDefinition ad1 = new AttributeDefinition();
  90.                     ad1.SetDatabaseDefaults();
  91.                     ad1.Tag = "tag";
  92.                     ad1.TextString = "textString";
  93.                     ad1.Constant = true;
  94.                     Matrix3d mat = br2.BlockTransform;
  95.                     ad1.TransformBy(mat);
  96.                     BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
  97.                     btr.AppendEntity(ad1);
  98.                     tr.AddNewlyCreatedDBObject(ad1, true);
  99.                     tr.Commit();
  100.                     ed.Regen();
  101.                 }
  102.  
  103.  
  104.             }
  105.             catch (Autodesk.AutoCAD.Runtime.Exception ex)
  106.             {
  107.  
  108.  
  109.                 ed.WriteMessage("\nError: {0}\n{1}", ex.GetBaseException(), ex.StackTrace);
  110.  
  111.  
  112.             }
  113.  
  114.  
  115.         }
  116.  
  117.  
  118.         void ad1_ObjectClosed(object sender, ObjectClosedEventArgs e)
  119.         {
  120.             Application.ShowAlertDialog("ObjectClosed");
  121.         }
  122.  
  123.  
  124.  

WILL HATCH

  • Bull Frog
  • Posts: 450
Re: adding/deleting block attributes
« Reply #31 on: February 01, 2013, 03:58:55 PM »
Thanks for that, I didn't know how to use the ObjectClosed event before this example...

I put your code into my compiler and didn't do anything aside from changing line 109 so it would compile, uncommenting line 47 where you lock the position in the block, and commenting out line and 70 where you reopen ad for write. Everything worked...  What version are you using?? Any add ons?

changed line 109 to:
Code - C#: [Select]
  1. Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage("\nError: {0}\n{1}", ex.GetBaseException(), ex.StackTrace);

Editor output after running:
Command: TRANSACTIONTESTING

Select attribute to add:  (BTW I never thought to simply check ad.IsDisposed)
Nothing Selected.

Select attribute to add:
Select block to append attribute:
693813248
False
MYTAGRegenerating model.
Regenerating model.


I'm even more confused at this point, I've read through the ARX documentation and everything there seems to agree with what you're telling me but it's not what I'm seeing  :lmao:
« Last Edit: February 01, 2013, 04:02:26 PM by WILL HATCH »

Jeff H

  • Needs a day job
  • Posts: 6150
Re: adding/deleting block attributes
« Reply #32 on: February 01, 2013, 07:43:43 PM »

2013 Vanilla flavour but this machine Design Suite(MEP, Revit, and crap like SkecthBook Designer that f**ks up all your dynamic blocks with wipeouts being stretched--sotty for the rant)

I thought a ObjectId or using the UnmanagedObject property would be valid until its database is destroyed which it is not ,but how your getting around not closing it or modifying it without opening it, I have no idea.


Does the ObjectClosed Event fire?


Wonder if OpenedForModify event fires before you erase it.


I really do not know,
Speaking of dispose earlier and to add another point I have code that plays different fart sounds for dispose.
A  loud, hard, quick trumpet sounding fart for when I explicitly call dispose on it, and a long slow squeaker if called in Finalization method
Which makes complete sense to me so it goes to show they could be doing anything they want in Dispose call.


 





WILL HATCH

  • Bull Frog
  • Posts: 450
Re: adding/deleting block attributes
« Reply #33 on: February 01, 2013, 09:56:00 PM »
 :lmao:
I remember coming across your notifier before.
The closed notification fires properly, at the very end of the command, and again when I hit undo, etc.  I'll add some more notifications and post them to the command line so I can show you here next week.

TheMaster

  • Guest
Re: adding/deleting block attributes
« Reply #34 on: February 02, 2013, 12:31:35 PM »
Hugo, Jeff,

What version are you using?  I'm trying to wrap my head around why things are working here if they object is apparently closed with the transaction  :-o.  If this is something version dependent then my code will be failing on different versions of AutoCAD... I can see how it would make logical sense that as the transaction was disposed the objects opened for write would be downgraded to read only to prevent any modification later.  Can anybody explain what is going on here?

Cheers

Only the outer-most transaction actually closes an object (or cancels it if the transaction is aborted). Inner or nested transactions are only markers that tell the transactionmanager what objects belong to what transactions. If you open an object for write in a transaction, the object stays open for write until the outer-most transaction is comitted or aborted. You will find that objects that are opened for read may still be usable after the outer-most transaction they were opened in has ended, but that is undocumented behavior that should never be relied on.

WILL HATCH

  • Bull Frog
  • Posts: 450
Re: adding/deleting block attributes
« Reply #35 on: February 02, 2013, 01:04:51 PM »
So that said, me experiencing objects which are still writable after a transaction is an anomaly that shouldn't happen   :blank:
I'm going to try to figure out why this is happening... I have written several functions that use this methodology...

How does that translate to your GetObjects extension method or the standard ObjectId.GetObject method? Do I need to use those inside a transaction to increase the stability of my code on different platforms?

owenwengerd

  • Bull Frog
  • Posts: 451
Re: adding/deleting block attributes
« Reply #36 on: February 02, 2013, 04:43:10 PM »
So that said, me experiencing objects which are still writable after a transaction is an anomaly that shouldn't happen   :blank:

I don't think you understood Tony's explanation. If you modify a database resident object, and AutoCAD does not close with a fatal error, then the object is open, period. Either it was opened directly, or it belongs to an open transaction. It sounds like the latter in your case. It doesn't have to be a transaction that your code started. You're probably using a vertical that starts a transaction every time a command executes. If you are, your code will fail in vanilla AutoCAD.

WILL HATCH

  • Bull Frog
  • Posts: 450
Re: adding/deleting block attributes
« Reply #37 on: February 02, 2013, 07:09:17 PM »
Thanks for explicitly pointing out some versions will create a transaction implicitly... I was going to try to add an event to top transaction being opened and closed and see if that happens at the start and end of every routine.

In our office we run mechanical 2012 and also CADWORX on regular autocad 2012

TheMaster

  • Guest
Re: adding/deleting block attributes
« Reply #38 on: February 28, 2013, 12:21:06 AM »
So that said, me experiencing objects which are still writable after a transaction is an anomaly that shouldn't happen   :blank:
I'm going to try to figure out why this is happening... I have written several functions that use this methodology...


I didn't say writeable, I said that objects that were opened for read can still be accessed after the outer-most transaction they were opened in has ended. As far as I know, if an object was obtained from a transaction using OpenMode.ForWrite, the transaction will close the object when it ends (the outer-most transaction, that is), and you shouldn't be able to modify any object after that happens. 

Quote


How does that translate to your GetObjects extension method or the standard ObjectId.GetObject method? Do I need to use those inside a transaction to increase the stability of my code on different platforms?

Use those as opposed to ..... ?

WILL HATCH

  • Bull Frog
  • Posts: 450
Re: adding/deleting block attributes
« Reply #39 on: February 28, 2013, 01:26:42 PM »
You can pretty well ignore those questions at this point... There was a transaction being wrapped around my command that I was unaware of and it was the reason for the confusion.

Thank you for the clarification!