catching an invalid entity name

catching an invalid entity name

JamesMaeding
Advisor Advisor
4,278 Views
27 Replies
Message 1 of 28

catching an invalid entity name

JamesMaeding
Advisor
Advisor

I have code that loops through a selection set, and it fails on drawings with slight corruption.

I ran AUDIT and it cleaned the corruption, but I want to detect what drawings have invalid entitiy names.

 

I tried many things, like:

(vl-catch-all-error-p (vl-catch-all-apply '(lambda () (SETQ OBJ (vlax-ename->vla-object (SSNAME CALLOUT-SS INDEX))))))

 

and so on, but those do not think there is an error.

But then this fails on same ename:

(SETQ ENAME (SSNAME CALLOUT-SS INDEX))

 

so the (vl-catch-all-apply... is not "catching", its letting the error by.

Any ideas on how to gracefully catch the invalid entity?

 

In my case, the invalid entity is a simple block with one attribute, not some huge AEC monster thingy.

I do want to keep this to lisp. I'm guessing its easy with .net.

thanks

 


internal protected virtual unsafe Human() : mostlyHarmless
I'm just here for the Shelties

0 Likes
4,279 Views
27 Replies
Replies (27)
Message 2 of 28

SeeMSixty7
Advisor
Advisor

The object exists in your code, so that's not the issue. One thing to do is take it a step further and access a property on the entity via an object property call that you know all the object will have like a layer. So trap the level to get the object and then trap again at the property level.

 

Good luck

 

 

0 Likes
Message 3 of 28

JamesMaeding
Advisor
Advisor

Great idea, I tried is just now and amazingly I can get the layer of the item:

 

(IF (AND (NOT (VL-CATCH-ALL-ERROR-P (VL-CATCH-ALL-APPLY '(LAMBDA () (SETQ OBJ (VLAX-ENAME->VLA-OBJECT (SSNAME CALLOUT-SS INDEX)))))))
              (NOT (VL-CATCH-ALL-ERROR-P (VL-CATCH-ALL-APPLY '(LAMBDA () (SETQ LAY (VLAX-GET-PROPERTY OBJ 'LAYER))))))
     )

That and statement evaluates to true.

the lay variable is a layer an xref is on, so I was wrong, the item with invalid ename is an xref.

I am not doing any modifications, just using this on an ssget.

 

of course the (SETQ ENAME (SSNAME CALLOUT-SS INDEX)) immediately fails, as well as if I inspect the obj var in VLIDE.

This is nuts, but honestly not that surprising, as we deal with files from many consultants.

I see so much screwed up stuff these days, and we run incoming files through the Civil Batch Converter of civil3d.

I'll keep on this as there must be something that can be caught.

 


internal protected virtual unsafe Human() : mostlyHarmless
I'm just here for the Shelties

0 Likes
Message 4 of 28

patrick_35
Collaborator
Collaborator

Hi

 

And with vlax-erased-p ?

Otherwise, an example will help in understanding

 

@+

0 Likes
Message 5 of 28

SeeMSixty7
Advisor
Advisor
Bummer that didn't work. I've had some issues like this on occasion as well before, and that typically got me there.

Can you upload a sample drawing and circle what you believe is the corrupt ent and your code?
0 Likes
Message 6 of 28

john.uhden
Mentor
Mentor
Might the Civil Batch Converter be to blame?

John F. Uhden

0 Likes
Message 7 of 28

JamesMaeding
Advisor
Advisor

ah, but wait.

looks like trying to get the name of the insert catches(for my bad drawing at least), like:

(NOT (VL-CATCH-ALL-ERROR-P (VL-CATCH-ALL-APPLY '(LAMBDA () (VLA-GET-name OBJ)))))

 

that only makes sense to use on inserts though. Many other entitieses do not have a name property.

 

As I played with the drawing, I realized the ename is only invalid when I use (ssget "x" '((0 . "INSERT"))) to get the inserts.

I narrowed down the xref that is "invalid" and can do anything I want if I don't select it with ssget "x".

 

The fact is the drawing has a corruption that can be fixed with an Audit, so who really cares why this is all happening.

I just have tools that automatically batch update things based on blocks with attributes so need that ssget "x" to not choke.

 

I am not sure how to deal with other entities that are invalid, just inserts so far.


internal protected virtual unsafe Human() : mostlyHarmless
I'm just here for the Shelties

0 Likes
Message 8 of 28

dbroad
Mentor
Mentor

Whenever you decide to use vl-catch-all-apply, you should ask yourself if you care why something is not failing. If the answer to that is yes, then you need to explore the reporting features built-in to the feature. Obviously, from your post, you care about why things are failing and are complaining about the lack of reporting.

But when you choose to use vl-catch-all-apply, you are taking on the task of managing reporting yourself. Look up the vl-catch-all-error-message function.

For your code, which doesn't have sufficient right parentheses BTW.

 

Spoiler
(IF
  (AND (NOT
	 (VL-CATCH-ALL-ERROR-P
	   (VL-CATCH-ALL-APPLY
	     '(LAMBDA ()
		(SETQ
		  OBJ (VLAX-ENAME->VLA-OBJECT (SSNAME CALLOUT-SS INDEX))
		)
	      )
	   )
	 )
       )
       (NOT
	 (VL-CATCH-ALL-ERROR-P
	   (VL-CATCH-ALL-APPLY
	     '(LAMBDA () (SETQ LAY (VLAX-GET-PROPERTY OBJ 'LAYER)))
	   )
	 )
       )
  )
)


Here you need to save:
1)The ename from (ssname.... ) before you save
2)The obj variable.

 

Unless you have localized OBJ, then OBJ in the code could be whatever it was before the code started. With vl-catch-all-apply, there is no error and therefore no error handling or break on error or error tracing. All you have is assumptions unless you take control.

After adding the save steps above, trap the error. Don't just pass it to vl-catch-all-error-p. Save the return value of the vl-catch-all-apply expression. It may be as simple as a failure to supply sufficient arguments to the vl-catch-all-apply function. In your code, you should include a null list if for documentation purposes if not required. Once you have saved it, you can check it.

I would suggest that you replace vl-catch-all-apply with the apply function until you understand the errors.

 

Spoiler
;;testing strategy to make sure obj, en, and cape are not using previous values
(setq obj nil
en nil
cape nil
cape2 nil
)
(IF (VL-CATCH-ALL-ERROR-P ;;LINE NUMBER 50 (setq cape (VL-CATCH-ALL-APPLY '(LAMBDA () (SETQ en (SSNAME CALLOUT-SS INDEX) OBJ (VLAX-ENAME->VLA-OBJECT en) )) nil ))) (PROGN (princ (strcat "\nVL-CATCH-ALL-APPLY ERROR AT LINE #50: " CAPE)) (EXIT)) (IF ;;LINE NUMBER 64 (VL-CATCH-ALL-ERROR-P (setq cape2 (VL-CATCH-ALL-APPLY '(LAMBDA () (SETQ LAY (VLAX-GET-PROPERTY OBJ 'LAYER))) nil ))) (PROGN (princ (strcat "\nVL-CATCH-ALL-APPLY ERROR AT LINE #64: " CAPE2) ) (EXIT)) (PROGN ;;DO YOUR STUFF HERE ) ) )

 

Architect, Registered NC, VA, SC, & GA.
0 Likes
Message 9 of 28

JamesMaeding
Advisor
Advisor

actually I would say I don't care in this case why its failing, as I just skip any entity that is, or stop the routine and tell the user their drawing is ugly.

Does not matter, your comment applies to many situations where I do care, so want to understand your idea.

I'll see if vl-catch-all-error-message  helps.

I use the VLIDE so easily catch paren matching errors, just got sloppy pasting in or something.

Also, all variables are localized, but setting obj to nil and then testing if its nil after the assignment would be more conservative.

I'll play a bit more.

 

John asked if the c3d civil batch converter could be the issue, and its not.

I do not run that on my sheets, just incoming files I use for bases (xrefs).

The xref with invalid ename is super clean when I open it. And I've struggled with dirty drawings for so long now my standard of clean is pretty high.

 

Awesome comments from all so far, thx


internal protected virtual unsafe Human() : mostlyHarmless
I'm just here for the Shelties

0 Likes
Message 10 of 28

john.uhden
Mentor
Mentor
Have you tried using (entget)?

John F. Uhden

0 Likes
Message 11 of 28

JamesMaeding
Advisor
Advisor

sure, but you have to feed entget an ename, and in my case getting that ename with (ssget) works, and (ssget "x") gets the ename but its invalid.

I think you meant (entsel...)

That would work, as any hand selection method works.

Its the "x" in ssget that is an issue - no idea why though.

 

entget was actually the original thing that failed.

It would be intereting to see if .net choked on the ss also.


internal protected virtual unsafe Human() : mostlyHarmless
I'm just here for the Shelties

0 Likes
Message 12 of 28

ВeekeeCZ
Consultant
Consultant

Just out of a curiosity... would you try this? btw by saying invalid, you mean nil?

 

(defun c:test ( / ss sl)
  (if (setq ss (ssget "_x"))
    (progn
      (princ (strcat "\nAll: " (itoa (sslength ss))))
      (setq sl (sstest ss))
      (princ (strcat "\nGood: " (itoa (sslength (car sl)))))
      (princ (strcat "\nWrong: " (itoa (sslength (last sl)))))
      ))
  (princ)
)


(defun sstest (ss / en i sg sw)
  (setq sg (ssadd)
	sw (ssadd))
  (if ss
    (repeat (setq i (sslength ss))
      (if (and (setq en (ssname ss (setq i (1- i))))
	       (entget en))
	(ssadd en sg)
	(ssadd en sw))))
  (list sg sw))
0 Likes
Message 13 of 28

dbroad
Mentor
Mentor

There is no reason why a normal selection set will cause an error when accessing with ssname unless the index is out of bounds. That means that the first object is index 0 and the last object index is sslength -1.

 

An attempt to access an entity that was erased between the time that the selection is made and the time the ssname is returned results in the deleted ename.

 

An attempt to access entity information with entget on a deleted entity will not result in an error, just nil.

 

A deleted object can be undeleted with (entdel ename).

 

Once it is undeleted, its information can be returned.

 

So there is something going on with your situation.  Post the whole code. The problem isn't in the posted section.

 

 

Architect, Registered NC, VA, SC, & GA.
0 Likes
Message 14 of 28

JamesMaeding
Advisor
Advisor

Doug,

remember that the sheet I am dealing with has a minor corruption.

Everything behaves if I Audit the file, it fixes one thing, and its related to the xref.

 

I agree with all you are saying and appreciate the attention you have given.

 

I'm still ripping the drawing apart, meanwhile also convincing someone in my riverside office that their drawings open slow due to civil3d styles, not excess annotation scales.... I must spend 2 hours a day helping teams keep their drawings stable.

thx


internal protected virtual unsafe Human() : mostlyHarmless
I'm just here for the Shelties

0 Likes
Message 15 of 28

JamesMaeding
Advisor
Advisor

Man, these DG's are running so slow these days.

Took chrome 20 seconds to show the reply text box once I hit reply.

 

more info, my audit shows this (the rest is generic):

Pass 2 700 objects auditedAcDbBlockReference(5A364) BTR Id invalid
AcDbBlockReference(5A364) could not be repaired. It will be Erased.

 

So the drawing has an invalid block "reference" - same as an insert?

 

The other thing is I erase everything in the drawing, and listed the rest by List command, All.

There were 19 AECC_Parcel entities, all with area 0.0.

 

You cannot erase them. They are not the problem though, just a sign of the mud this file must have been through.

I attached a drawing showing my problem.

open the vlide, paste this code, select it and right click, say Inspect. You will see the error and can test anything on it.

(SETQ SS (SSGET "X" '((0 . "INSERT"))))

 

thanks

 


internal protected virtual unsafe Human() : mostlyHarmless
I'm just here for the Shelties

0 Likes
Message 16 of 28

ВeekeeCZ
Consultant
Consultant
Autocad 2015 vanilla.
TEST routine showed me 19 good, one wrong.
AUDIT erased the wrong one.
(command "erase" (SSGET "X") "") erased 18 proxy objects.
Only a VIEWPORT left the drawing.
Not sure what that means...
0 Likes
Message 17 of 28

JamesMaeding
Advisor
Advisor

Yep, those proxy's are AECC_Parcels, and the funny thing is you cannot erase them in a c3d or acad session with object enablers.

That is why I purposefully do not install the OE's for acad.

 

An audit does erase the bad insert, just like I see.

 

The thing is, none of the bad entities seem to hurt anything else. My users can work on the sheet with no problems, plot and so on.

Then I go to run my construction notes list updater, and whamo.

 

Its rare behavior, throws programmers off because a corrupt drawing does not follow the rules...

 


internal protected virtual unsafe Human() : mostlyHarmless
I'm just here for the Shelties

0 Likes
Message 18 of 28

dbroad
Mentor
Mentor

There's no point in working on corrupt drawings. See command log for your drawing.

Spoiler
Command: AUDIT

Fix any errors detected? [Yes/No] <N>: y



Auditing Header


Auditing Tables


Auditing Entities Pass 1

Pass 1 3000 objects auditedAcDbViewport(65BEF)
Paperspace vport layer Not "0" "0"

Auditing Entities Pass 2

AcDbRegAppTable(9) Invalid AcDbRegAppTableRecord was removed.
Pass 2 700 objects auditedAcDbBlockReference(5A364) BTR Id invalid
AcDbBlockReference(5A364) could not be repaired. It will be Erased.
Pass 2 3000 objects audited
Auditing Blocks


0 Blocks audited



Auditing AcDsRecords

Regenerating model.

Total errors found 3 fixed 3

Erased 1 objects


Command: (setq ss (ssget "x" '((0 . "insert"))))
nil

 

Architect, Registered NC, VA, SC, & GA.
0 Likes
Message 19 of 28

john.uhden
Mentor
Mentor
My guess is that Putin hacked your servers.

John F. Uhden

0 Likes
Message 20 of 28

SeeMSixty7
Advisor
Advisor

What if you use the method we discussed before about accessing it via object methods, specifically ObjectName and then checked if it is ; ObjectName (RO) = "AcDbZombieEntity". Cheking the entity that is giving you grief it shows to be a Zombie. Then skip the entity and move on through your process. I'm running in AutoCAD 2017 Plain with out any OE's loaded. I assumed that was how you were running it. I believe your goal is to work through your process without getting bogged down on irrelevant entities. You can flag it for review to your group and move on.

 

Good luck.

0 Likes