Author Topic: UndoCtl group bit set, new database  (Read 6230 times)

0 Members and 2 Guests are viewing this topic.

T.Willey

  • Needs a day job
  • Posts: 5251
UndoCtl group bit set, new database
« on: December 15, 2014, 12:31:38 PM »
I am working on some code for some, so I cannot post the code and I do not want to get into too much detail publicly, sorry.  I know that can be a problem when looking for help.

The issue:  when the user edits the drawing with regular AutoCAD commands, and then wants to undo one or two of them, they all get undo'ed to the point where the drawing was first opened.

I am copying a bunch of objects from the currently opened drawing to a new database, new Database( true, false ), using WblockCloneObjects.  I am then closing the current drawing, without saving, and opening my new drawing.  Within the new drawing the UndoCtl system variable is set to 13 upon opening, meaning that a group is active ( even ending the group does not seem to work ).  This issue only occurs the first time the program is ran.  It also disappears when you close the new drawing and open it up again through AutoCAD commands.

I have tried setting DisableUndoRecording to true/false and that does nothing.  I have not seen anything else to try, and I am at my wits end.

I will try an answer any questions here, so others can learn also.

Thanks in advance.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

owenwengerd

  • Bull Frog
  • Posts: 451
Re: UndoCtl group bit set, new database
« Reply #1 on: December 15, 2014, 01:02:28 PM »
This is usually related to performing database or editor actions from a modeless or application context (such as during a windows message handler, or during a reactor callback).

T.Willey

  • Needs a day job
  • Posts: 5251
Re: UndoCtl group bit set, new database
« Reply #2 on: December 15, 2014, 01:42:09 PM »
Thanks, Owen.  I do not edit either drawing while my dialog is open.  I use a 'using' statement, and it only exists for a short period of time to gather information for use later.  I do not use a reactor, so I would not think there is any editing happening unless AutoCAD is firing on its own.

I will investigate further to make sure I understand fully your advice.

Edit:  Forgot to mention that my dialog is a modal dialog.
« Last Edit: December 15, 2014, 02:39:27 PM by T.Willey »
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

MexicanCustard

  • Swamp Rat
  • Posts: 705
Re: UndoCtl group bit set, new database
« Reply #3 on: December 15, 2014, 04:11:08 PM »
If you are opening the new drawing after it's creation, why not create the new drawing within the document manager and let it create it in the editor?  I have no idea if that would affect your issue but I would try it and see if it makes a difference.
Revit 2019, AMEP 2019 64bit Win 10

owenwengerd

  • Bull Frog
  • Posts: 451
Re: UndoCtl group bit set, new database
« Reply #4 on: December 15, 2014, 05:58:42 PM »
In what context are you creating your modal dialog (CommandMethod/LispFunction/etc.)? Are you using Application.ShowModalDialog()?

The basic problems is that an internal AutoCAD state is not getting properly ended, and so the internal UNDO state thinks there is an operation ongoing. Even though you are not modifying the database, it's possible that the call to WblockCloneObjects has some bearing on the problem. I would try to narrow it down by removing small pieces until the problem disappears.

T.Willey

  • Needs a day job
  • Posts: 5251
Re: UndoCtl group bit set, new database
« Reply #5 on: December 15, 2014, 06:13:18 PM »
If you are opening the new drawing after it's creation, why not create the new drawing within the document manager and let it create it in the editor?  I have no idea if that would affect your issue but I would try it and see if it makes a difference.

This would be a last resort, as the code is all written.  If I cannot make it work, then this is an option.  Thanks.

In what context are you creating your modal dialog (CommandMethod/LispFunction/etc.)? Are you using Application.ShowModalDialog()?

The basic problems is that an internal AutoCAD state is not getting properly ended, and so the internal UNDO state thinks there is an operation ongoing. Even though you are not modifying the database, it's possible that the call to WblockCloneObjects has some bearing on the problem. I would try to narrow it down by removing small pieces until the problem disappears.

It is a CommandMethod with the Session flag set.  I launch the dialog with just ShowDialog from an instance of the custom form.  I can start removing portions of the code to see if that helps.  Thanks.

This is just weird that it happens only on the first call of the program, and not something continuous.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

Jeff H

  • Needs a day job
  • Posts: 6150
Re: UndoCtl group bit set, new database
« Reply #6 on: December 15, 2014, 06:29:25 PM »
Database( true, false ) -> with second argument as false associates database with current document and in session context I thought the outermost undo marks are when you locked and unlocked the document.




T.Willey

  • Needs a day job
  • Posts: 5251
Re: UndoCtl group bit set, new database
« Reply #7 on: December 15, 2014, 07:47:02 PM »
I tried Database( true, true) also, and got the same issue.  I will check again when I try to figure out where its going wrong.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

owenwengerd

  • Bull Frog
  • Posts: 451
Re: UndoCtl group bit set, new database
« Reply #8 on: December 15, 2014, 08:19:23 PM »
It is a CommandMethod with the Session flag set.  I launch the dialog with just ShowDialog from an instance of the custom form.

Calling ShowDialog() is a bad idea, and very possibly the reason you're having problems. In any case, you should always use Application.ShowModalDialog().

T.Willey

  • Needs a day job
  • Posts: 5251
Re: UndoCtl group bit set, new database
« Reply #9 on: December 16, 2014, 12:45:10 AM »
Owen, thanks for the tip about ShowDialog.  That is how I have always called a dialog.  I will change from now on.


The issue seems to arise from a call to trans.AddNewlyCreatedDBObject( obj, true );.  If I comment this out, then the UndoCtl variable is set to 5, and undo's proceed like they should.  If I leave it commented out though, I receive an error of eWasOpenForWrite on the call to WblockCloneObjects, but only when selecting certain objects.

The situation:  I am exploding blocks and if their contents meet certain requirements, then they are added to the current database, with the ability to be copied to the new database.  I append the objects, as an entity, to the owner BlockTableRecord, and then call trans.AddNewlyCreatedDBObject( obj, true ).

I have some testing to do tomorrow, but am calling a quits for the night.

Thank you everyone for the tips and pointers.  They are very much appreciated.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

nekitip

  • Guest
Re: UndoCtl group bit set, new database
« Reply #10 on: December 16, 2014, 05:34:37 AM »
I'm sure you have tested this, but is it possible that you have some transaction somewhere open the whole time?

T.Willey

  • Needs a day job
  • Posts: 5251
Re: UndoCtl group bit set, new database
« Reply #11 on: December 16, 2014, 10:11:26 AM »
I'm sure you have tested this, but is it possible that you have some transaction somewhere open the whole time?

It does not look like it.  I use transactions only with 'using' statements.  Thanks for the idea.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

Jeff H

  • Needs a day job
  • Posts: 6150
Re: UndoCtl group bit set, new database
« Reply #12 on: December 16, 2014, 01:00:50 PM »
If a command is used to open the dialog then wouldn't anything done while that dialog is opened be nested inside its undo marks?

Think should only be for commands that do not modify database but you have NoUndoMarker CommandFlag.

T.Willey

  • Needs a day job
  • Posts: 5251
Re: UndoCtl group bit set, new database
« Reply #13 on: December 16, 2014, 02:51:35 PM »
If a command is used to open the dialog then wouldn't anything done while that dialog is opened be nested inside its undo marks?

Think should only be for commands that do not modify database but you have NoUndoMarker CommandFlag.

I check the system variable UndoCtl while my command is active, and it returns 5 ( meaning a group is not active ), so it does not look like the variable is getting set in my current document and carrying over to the newly created one.

I also just tried setting the CommandFlags to NoUndoMarker, and that did not solve the problem, which I am kind of glad about.

I will continue to investigate this today, but right now it is lunch time.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

T.Willey

  • Needs a day job
  • Posts: 5251
Re: UndoCtl group bit set, new database
« Reply #14 on: December 16, 2014, 05:41:22 PM »
The real issue seems that the current document is busy with something.  If I do not close it, then it the UndoCtl system variable is correctly set.  If I try and close it after I open the new drawing in the editor, then I get a message saying the drawing is busy.

Now to find where the document can be hanging up.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

nekitip

  • Guest
Re: UndoCtl group bit set, new database
« Reply #15 on: December 18, 2014, 05:46:29 AM »
meanwhile, if you are concerned just to make sure user don't undo all, you can try to add undo mark. This will not solve mystery, but at least users can undo all.
(again, without knowing your code, it's hard to tell)

Code - vb.net: [Select]
  1. Private Shared Sub makeUndoMark()
  2.             Dim db As Database = HostApplicationServices.WorkingDatabase()
  3.             Dim doc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.GetDocument(db)
  4.             Using l As DocumentLock = doc.LockDocument()
  5.                 Using trans As Transaction = db.TransactionManager.StartTransaction()
  6.                     trans.Commit()
  7.                 End Using
  8.             End Using
  9.         End Sub

T.Willey

  • Needs a day job
  • Posts: 5251
Re: UndoCtl group bit set, new database
« Reply #16 on: December 18, 2014, 11:14:39 PM »
I do have a transaction taking place on the newly opened drawing, but that does not seem to matter.


I have narrowed it down even further now.  The issues seems to only be related to dimension objects, but not all dimension objects.  I created a test drawing and added a dimension to it, and it works fine, but the drawing my customer supplied has dimensions that do not work.  For some reason I am getting an error of 'eWasOpenForWrite' each time I use the command.  I selected over 30,000 objects, and only ~1000 objects do not want to be copied, and they are all some form of dimension, AcDb*Dimension.  I make sure not to explode any dimension's BlockTableRecord.  I am at a lose as to why this is happening.  At least I got it down to one type of object, where I can repeat the error.  Now to figure why this is happen with dimensions.  I did try and Downgrade dimension objects, but that had no effect.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

nekitip

  • Guest
Re: UndoCtl group bit set, new database
« Reply #17 on: December 19, 2014, 01:35:11 AM »
interesting. never heard of dimensions acting this way
please keep informing us!

P.S.
can it be some of the failed dimensions have text override?
and maybe fields in it?
(shot in the dark)

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8722
  • AKA Daniel
Re: UndoCtl group bit set, new database
« Reply #18 on: December 19, 2014, 01:57:04 AM »
did you notice any fields? possibly being updated?

T.Willey

  • Needs a day job
  • Posts: 5251
Re: UndoCtl group bit set, new database
« Reply #19 on: December 19, 2014, 10:26:14 AM »
It is not working on any dimensions.  I just looked at one, and it does not have any text overrides.  I also check for fields, obj.HasFields, and if the object is DbText of MText then I convert the field to static text.  When I noticed that dimensions where the problem, I checked to see if they have anything like DbText or MText to convert a field, but saw none.  And, the file does not have any dimensions with fields.

Thanks for the ideas.

Maybe it is the flow of my code that is causing the issue.  The dimensions cause no issue if I do not explode any blocks and the UndoCtl issue does not exist either.  But, when I explode the blocks and call trans.AddNewlyCreatedDBObject( obj, true ); after I call aOwnRec.AppendEntity( ent );, where ent = obj - just the entity version of the dbobject, then the new file will have the UndoCtl issue but the dimensions will be copied over.  If I explode the blocks and only call aOwnRec.AppendEntity( ent ) then the UndoCtl issue is not there but no dimensions will be copied over.

I'm still searching for a way to have my cake and eat it to.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

T.Willey

  • Needs a day job
  • Posts: 5251
Re: UndoCtl group bit set, new database
« Reply #20 on: December 19, 2014, 11:35:05 AM »
I just created a dimension object with a field attached in my test drawing.  No matter what I do, I cannot convert, and keep the field converted, in the new database.  I am wondering if it is because I copy it over before the trans.Commit() call?  I would think not, because the objects that get exploded copy over just fine, and they all happen for the Commit() call.

This passage from the Arx docs is a little scary for my current situation.
Quote
Modifying a dimension in a noncurrent database will cause its DimBlockId to be set to NULL. This ensures that the next time the database is loaded as the current drawing, a new dimension block will be created, and the old one will be purged. This is necessary because dimension blocks in noncurrent databases cannot be created or modified. A dimension opened for write in a noncurrent database will have its DimBlockId set to NULL during close. This may generate problems for applications.

Even though I am not changing the dimension block in the non-current database, as I am changing it before I copy it over to the non-current database.

Edit:  Maybe I should clarify a little.  I can change the field to a static value.  I then apply it to the dimension, dim.DimensionText, which is supposed to allow for text overrides, but when I open the new drawing the field is still there showing all 'x' since the link is gone.
From Arx docs
Quote
Setting the text using the Dimension.DimensionText property will override the default value.
« Last Edit: December 19, 2014, 11:38:38 AM by T.Willey »
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

T.Willey

  • Needs a day job
  • Posts: 5251
Re: UndoCtl group bit set, new database
« Reply #21 on: December 19, 2014, 11:54:20 AM »
Okay, the issue with dimensions and fields is solved, partially.  The issue from the help file still shows ( where the dimension does not show the correct information until it is edited in such a way to cause the dimension to be redrawn, and a regen will not do it ), but hopefully that is a small issue.  How I did it:
step through the dimension block's definition
when an mtext object is found, use dim.FieldToMText( mtext ), using the mtext object found
Edit:[ on the mtext object, use the method ConvertFieldToText.  The above caused errors. ]
remove the field from the dimension, dim.RemoveTextField()
copy the text string from the mtext object to dim.DimensionText

The main issue with dimensions still is there.  Off to conquer that issue.
« Last Edit: January 19, 2015, 10:01:02 PM by T.Willey »
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

T.Willey

  • Needs a day job
  • Posts: 5251
Re: UndoCtl group bit set, new database
« Reply #22 on: January 08, 2015, 10:40:27 AM »
The main issue seems to have something to do with the 'explode' method supplied by Autodesk's API.  When I build my own 'explode' function, the UndoCtl variable is set correctly, but I run into an error.  I forget the exact error now, but it stated something like 'max reader' reached.  When looking on the net I saw mention of this and opening an object too many times, which makes sense since when I start a drawing could I have 800 items in it, but when I'm done it will have 38,000 items.  I also read what when using 'DeepObjectClone' you have to call it once per owning object, so that my be where my issue of 'max reader' is arising.

I will continue to post in this thread until I am done with the project, just in case anyone might find it useful in the future.  Thanks again.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.