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

Program crashes when trying to access modelspace

17 REPLIES 17
SOLVED
Reply
Message 1 of 18
Keith.Brown
1622 Views, 17 Replies

Program crashes when trying to access modelspace

I have a program where I am inserting blocks at specific points in model space.  I have successfully been able to create a subroutine that will accept a block name, a point3D Location and a layer name and and insert the specified block at the specified location on the specified layer.  What I need to do now is to cycle through model space and find all of the pipe objects in model space.  I then find the endpoint of each pipe and insert a block at that location.  The problem that I am having is that the program crashes when I try to find the objectid of modelspace.  I am using the technique discussed in this thread by Jeffrey_H.

 

VB.NET Access to Styles

 

Below is the code that I am trying to get to work.

 

        'Test Command to insert the some blocks into the drawing
        <CommandMethod("TrimbleTestBlocks")> _
        Public Sub TrimbleTestBlocks()

            'Get the editor object
            Dim doc = AcApp.DocumentManager.MdiActiveDocument
            Dim db = doc.Database
            Dim ed = doc.Editor

            Try


                'Get Model Space Block Table Record
                Dim mdlspace As BlockTableRecord = SymbolUtilityServices.GetBlockModelSpaceId(db).GetObject(OpenMode.ForRead)

                'Start the transaction
                Using tm As Transaction = db.TransactionManager.StartTransaction

                    'Cycle through each object in modelspace
                    For Each objid As ObjectId In mdlspace

                        'If the object is a Pipe Object then add a block to the end of it
                        If objid.ObjectClass.Name = "AecdbPipe" Then

                            'At this point we know the object is a pipe so create a reference to it.
                            Dim mpipe As Pipe = tm.GetObject(objid, OpenMode.ForRead, True)

                            'Get the endpoint of the pipe
                            Dim PipeEndpoint As Point3d = mpipe.EndPoint

                            'Insert the block at the endpoint of the pipe
                            TrimbleInsertBlockAtPoint(INS250, PipeEndpoint, HYD250)

                        End If
                    Next

                End Using

            Catch ex As Exception
                MsgBox(ex.Message)
            End Try

            'TrimbleInsertBlockAtPoint(INS250, New Point3D(0, 0, 0), HYD250)
            'TrimbleInsertBlockAtPoint(INS375, New Point3d(0, 10, 0), HYD375)
            'TrimbleInsertBlockAtPoint(INS500, New Point3d(0, 20, 0), HYD500)
            'TrimbleInsertBlockAtPoint(INS625, New Point3d(0, 30, 0), HYD625)
            'TrimbleInsertBlockAtPoint(INS750, New Point3d(0, 40, 0), HYD750)
            'TrimbleInsertBlockAtPoint(INS875, New Point3d(0, 50, 0), HYD875)
            'TrimbleInsertBlockAtPoint(INS875, New Point3d(50, 50, 50), HYD875)

        End Sub

 

This is the line that crashes on me

 

                'Get Model Space Block Table Record
                Dim mdlspace As BlockTableRecord = SymbolUtilityServices.GetBlockModelSpaceId(db).GetObject(OpenMode.ForRead)

 

Does anyone have any ideas on why this is crashing the program?  I just started programming dotnet this weekend and my head is starting to explode.

 

My end goal is to cycle through every pipe in model space.  If the pipe belongs to a specified system definition then find the pipe size and insert a corresponding block on the endpoint of the pipe.  I then want to export the blocks to a new drawing to be imported into a trimble unit for locating inserts on a deck. 

 

Thanks for any help in advance.

17 REPLIES 17
Message 2 of 18
Artvegas
in reply to: Keith.Brown

Hi,

 

I don't think that the SymbolUtilityServices.GetBlockModelSpaceId() function is the officially recommended way to obtain model space.

 

Check out the following link from the AutoCAD .NET Developer's Guide:
http://exchange.autodesk.com/autocad/enu/online-help/browse#WS73099cc142f48755f2fc9df120970276f7a33....

 

I think this is what you are looking for. It gives you the recommended method for iterating entities in model space with samples.

 

Hope this helps.
Art

Message 3 of 18

You are trying to add blocks into model space when it is only opened for read. Change it to " OpenMode.ForWrite"

 

HTH

Message 4 of 18

I found the problem.  The line that was causing the crash was outside the umbrella of the transaction.  As soon as I moved it inside the transaction block of code it stopped crashing but I still have some logic errors. 

 

Brent, I am taking care of opening model space for write inside of the subroutine that adds the block.

Message 5 of 18
Keith.Brown
in reply to: Keith.Brown

I had also forgotten to commit the transaction when I was finished iterating through all of the pipes in a drawing.  The code now works as written but I am having a problem figuring out how to find the pipe system definition, routing preference, and the pipe size.  I need that information to figure out which block to add to the end of the pipe.  Does anyone know how to access this information?  They are not properties of the pipe object.

 

Below is the code that worked as expected.

 

        'Test Command to insert the some blocks into the drawing
        <CommandMethod("TrimbleTestBlocks")> _
        Public Sub TrimbleTestBlocks()

            'Get the editor object
            Dim doc = AcApp.DocumentManager.MdiActiveDocument
            Dim db = doc.Database
            Dim ed = doc.Editor

            Try

                'Start the transaction
                Using tm As Transaction = db.TransactionManager.StartTransaction

                    'Get Model Space Block Table Record
                    Dim mdlspace As BlockTableRecord = SymbolUtilityServices.GetBlockModelSpaceId(db).GetObject(OpenMode.ForRead)

                    'Cycle through each object in modelspace
                    For Each objid As ObjectId In mdlspace

                        'If the object is a Pipe Object then add a block to the end of it
                        If objid.ObjectClass.Name = "AecbDbPipe" Then

                            'At this point we know the object is a pipe so create a reference to it.
                            Dim mpipe As Pipe = tm.GetObject(objid, OpenMode.ForRead, True)

                            'Get the endpoint of the pipe
                            Dim PipeEndpoint As Point3d = mpipe.EndPoint

                            'Insert the block at the endpoint of the pipe
                            TrimbleInsertBlockAtPoint(INS250, PipeEndpoint, HYD250)

                            'Now that we have added a block to a pipe, write a message to the command line
                            ed.WriteMessage("Block added at " & PipeEndpoint.ToString & vbLf)

                        End If

                    Next

                    'Commit the transaction
                    tm.Commit()

                End Using

                'Catch any exceptions and generate a generic message to the command line
            Catch ex As Exception
                ed.WriteMessage("There was an error adding the blocks to the drawing..." & vbLf)
            End Try

        End Sub

 

 

 

Message 6 of 18

Just a thought - I haven't dealt with it much, but have you tried attaching XData to your pipes/blocks then accessing it as needed?

Message 7 of 18

I guess I should have mentioned that I was using Autocad MEP.  So the pipes are already in the drawing and they already have the information attached to them.  I just have no idea on how to read it.  There is not alot of information on the API for Autocad MEP or Autocad Architectural so I am fumbling around alot trying to figure out how to do things.  So far everything I have done is a pretty straight forward method and is outlined in the Autocad API documentation.  I hit the wall once I came to trying to read the information attached to the piping objects.

Message 8 of 18
cadMeUp
in reply to: Keith.Brown

I'm assuming you are using AutoCAD MEP versions 2009 thru 2012?, in the MEP program installation folder, you can find quite a few sample NET projects for MEP under the 'Sample\VB.NET' folder or 'Sample\CS.NET' folder. Be sure to check out the 'ReadMe.txt' files for each project. You should be able to find a sample that shows how to get to the info you want.

 

Maybe check out the code in the samples:

 

MepUtilities (has a function 'GetPartSizeName()' in the DataUtilities.vb code file)

ExportToExcel

GetEngineeringData

SystemDefs

 

If you can't find the sample files in your program folder there are zip files attached of the samples for 2010, 2011, & 2012.

Message 9 of 18
Keith.Brown
in reply to: cadMeUp

Thanks for the information cadMeUp.  I did look through those but I will go through them again and see if i missed anything.  The system definations examples show how to print out all of the system defintions in the drawing but unless I am missing something, they dont show how to find out what the system defintion is for an object in the drawing.  The getpartsizename() has to do with quering a catalog but maybe I can use the same method to find the information about the part.  If I can establish which catalog the part came from then query the catalog with the part guid, i might be able to get the desired information.  It just seems that it is going the long way around to find the information that should already be in the database.  Using that method, what would happen if the catalog no longer exists? or isnt loaded?

 

I think that some of the answer lies in the excel example.  They are accessing some of the information that is attached to the part but not the system definition or the routing preference.  I think I can grab the pipe size from this information though.  Thanks again for reminding me to look here.  Now I just need to roll up my sleeves and figure out what they are doing.

Message 10 of 18
cadMeUp
in reply to: Keith.Brown

Have a look at the attached code file for VS 2008 C#, MEP 2012...

Message 11 of 18
Keith.Brown
in reply to: cadMeUp

That is exactly the information that I was looking for!  I had figured out how to get the part data from the pipe object from the ExportToExcel example but was still at a loss on how to extract the routing and system information.  Thank you for the code!

 

I did look over the getengineeringdata example real quick but didnt see anything about routing preferences in it.  I guess I should have compiled and ran the code and then I would have seen that it held the routing preference information.  Lesson Learned.

 

One more quick question for you, how can you set the routing preference and the system definition?

Message 12 of 18
Keith.Brown
in reply to: Keith.Brown

I did compile and run the GetEngineeringData example that ships with Autocad MEP and there is an error in the logic.  They ask you to select any mep object and then it finds the engineering data by its context and its index number and then prints it out.  The only problem is that the specific data that it is looking for seems to only be attached to a duct object.  Maybe this was by design which is why they have several catch statements in the program but from the Comments in the program it is supposed to work for any MEP object.

Message 13 of 18
jeff
in reply to: Keith.Brown

Its been a while but does this help?

http://www.theswamp.org/index.php?topic=37159.msg423214#msg423214

 

Mostly C# but here is some VB from link above

 

  <CommandMethod("PipePrefVB")> _
        Public Sub PipePrefVB()

            Dim doc As Document = Application.DocumentManager.MdiActiveDocument
            Dim db As Database = doc.Database
            Dim ed As Editor = doc.Editor

            Using trx As Transaction = db.TransactionManager.StartTransaction()

                Dim pipeId As ObjectId = ed.GetEntity("Select Pipe").ObjectId
                Dim member As Member = trx.GetObject(pipeId, OpenMode.ForWrite)
                Dim dataRecord As DataRecord = PartManager.GetEngineeringData(member)

                Dim pipePrefDic As New PipeDbServies.DictionaryPipePartRoutingPreferencesStyle(db)
                Dim newPipePrefId As ObjectId = pipePrefDic.GetAt("Brazed Copper")

                Dim routingPeference As DataField = dataRecord.DataFields.FindByContext(Context.RoutingPreferenceId)
                routingPeference.ValueObjectId = newPipePrefId

                PartManager.SetPartData(member, dataRecord)
                PartManager.SetEngineeringData(member, dataRecord)

                trx.Commit()
            End Using
        End Sub

 

You can also find your answers @ TheSwamp
Message 14 of 18
cadMeUp
in reply to: Keith.Brown

I'm not surprised to see there is an error, but samples are always good for tweeking anyway!

 

I saw Jeff's post about setting the data on the part, that is what I was going to suggest the methods:

 

PartManager.SetPartData(member, dataRecord)

PartManager.SetEngineeringData(member, dataRecord)

 

The 'PartManager' object has quite a few very useful static methods.

 

In the code file that I attached earlier, there is a commented out foreach loop, if you uncomment it and run the command it will list all of the data and context and index number for each data item. Might be useful to know what other data you can get out of the dataRecord. That should work for any Member object, of course my code only passes a pipe object specifically.

Message 15 of 18
cadMeUp
in reply to: Keith.Brown

I forgot to mention, another way of accessing the various styles and definitions in the database is thru the Named Objects Dictionary, see the attached code file for a sample...

Message 16 of 18
Keith.Brown
in reply to: cadMeUp

Thanks for all the information!  I was able to use the examples posted by Jeff and cadmeup and get the information I wanted from the pipeobject.  I have not tried setting the system definition or routing preference but I plan to tackle that this weekend.  I am having another issue but will start another thread so as not to run this one to death. 

 

Thanks again for all of the help.  It is difficult finding information on Autocad Architectural and Autocad MEP and the community seems to be the only place to find it right now without spending a ton of time researching.

Message 17 of 18
jeff
in reply to: Keith.Brown

That might have something to do with how horrible the documentation(if you can even call it that) for MEP and ARCH is.

 

The documentation just shows the signatures and have not updated or still send 2010 or 2009 with latest releases.

You can also find your answers @ TheSwamp
Message 18 of 18
Keith.Brown
in reply to: jeff

The coding examples that ship with the product do help a little bit but even they are not documentated that well.  I can't imagine that it would take someone with a good understanding of the .net api for MEP and Arch very long to go through and document them enough so someone could understand them better.  Not everyone looking at the samples has a degree in computer science or a background in .net.  I took a couple programming classes 20 years ago and decided to take the plunge into learning .net just recently.   The basic concepts of programming are still there but learning the specifics of the api is proving quite challenging.  MEP is a great program but could be so much more with just a little bit of tweaking.

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

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report

”Boost