Filtering Out xRef Objects in Python3 Node

Hello All,

I am hoping someone can give me a boost in my quest to refactor a work tool in a python3 node. With great guidance from Kean Walmsley’s “Through The Interface”, I created a simple tool for work some time ago in C# but it was sadly strangled by the CIO whose assessment is that custom .dlls are too much of a security risk. I recently was given another shot with my supervisor’s notion that Dynamo might be acceptable but with my security restrictions, I have to do it with no custom nodes, no package downloads and the company’s latest mass install version (Civil3D 2024). I’ve learned as much as I can from Jacob and Sol from the great Dynamo Office Hours series and have read through the forum and other sources that have helped me work through many things thus far, but I cannot for the life of me figure out how to test for and filter out of my list, any xref. This is the C# code that does it:

Any thoughts would be very appreciated

CAN YOU SEE THIS CODE

1 Like

Thank You for that response. I’ve been trying similar and it is not working. I realize I should have given more background. I have been able to get a selection set and that looks like this:


I am then able to get objects from that set with this line that I found in this forum (thanks for that):

and that presents a list that looks like this (4 lines and an xref selected):


This is where the problem comes in I think. I have objects but not Dynamo objects? My original goal was just to get the objects and then move on in Dynamo but I could not figure out how to make these objects be objects recognized by standard Dynamo nodes. I know I could with the Civil3DToolkit but my company does not present that option. So I decided perhaps I could just do everything in the the one python node but I still seem to be stuck with what this list of objects actually is vs. what it needs to be? The goal right now is to step through this list and filter out any xref, then move on.
This seems to just lock me up, not sure why that doesn’t work:
image
If I try this, just to see what I get and select just the xref:

I get false, so the Autodesk.AutoCAD.DatabaseServices.BlockReference I have is not recognized as the BlockReference I’m comparing to so I seem to just not have what I need.
If I try this to see if I get anything, it throws an exception:


I thought I was close and everything I try just goes the wrong way it seems. Sadness :0(
If anyone has any other thoughts, I really appreciate a push in the right direction.

here is an example of conversion (I haven’t tested on all types of objects)

# Load the Python Standard and DesignScript Libraries
import sys
import clr

# Add Assemblies for AutoCAD and Civil3D
clr.AddReference('AcMgd')
clr.AddReference('AcCoreMgd')
clr.AddReference('AcDbMgd')
clr.AddReference('AecBaseMgd')
clr.AddReference('AecPropDataMgd')
clr.AddReference('AeccDbMgd')

# Import references from AutoCAD
from Autodesk.AutoCAD.Runtime import *
from Autodesk.AutoCAD.ApplicationServices import *
from Autodesk.AutoCAD.EditorInput import *
from Autodesk.AutoCAD.DatabaseServices import *
from Autodesk.AutoCAD.Geometry import *

# Import references from Civil3D
from Autodesk.Civil.ApplicationServices import *
from Autodesk.Civil.DatabaseServices import *

clr.AddReference('AutoCADNodes')
import Autodesk.AutoCAD.DynamoNodes 
from Autodesk.AutoCAD.DynamoNodes import AutoCADUtility

# The inputs to this node will be stored as a list in the IN variables.
dataEnteringNode = IN

adoc = Application.DocumentManager.MdiActiveDocument
editor = adoc.Editor
obj = IN[0]
# get internal / unwrap object
acadObject = obj.InternalDBObject
# convert / wrap to DynamoObject
dynObject = AutoCADUtility.CreateDynamoObject(acadObject, False)

# Assign your output to the OUT variable.
OUT = acadObject, dynObject

Thank you for that. I actually might be on my way, or I’ve gone backward.. not sure, but I found this line from Paolo on another post:
image

and that has given me a list of objects that works in Dynamo. I had previously created a graph that was working on my personal machine using the Civil3DToolkit Select Objects node but due to my employer’s restrictions, I cannot use that graph with that node so I had been trying to recreate the select objects functionality in a python node and with this missing line, I have just finished verifying that I now have managed to get that done. My prior graph is working with my python select objects node so YAY!

I still don’t know how to filter out an xref from the list but now I can move forward with Dynamo objects and look for nodes that might work. Thanks all :0)

maybe you can at least use the packages made by Autodesk

Thanks, I am hoping that things may become easier if I can break through. I think the issue with the packages right now for the most part would be the effort of the IS team to get the packages on individual machines and I am trying to pioneer a dedicated effort at coding automation for the company so I am trying to show them the value without having to ask for any effort on their part, which could shut me down again. I honestly don’t believe my prior C# solution is any major security risk but I got shut down because the company does not have the structure to vet my code. This opportunity to try with Dynamo is another shot for me and I hope that if the company starts getting behind it, getting the packages by Paolo as well as the packages that Jacob and Sol recommend on the Dynamo Office Hours videos. I actually thought the same when I started. I immediately added that package then had to take it off until I might get approval.

Watch out that the Civils 3d Toolkit does not work for civils 3d 2025 and is unsupported anymore.

So watch out relying on this package going forward as you will have to decide on a new method anyway in the future which does not use this package

1 Like

On an aside, you should be able to wrap the packages into a custom installer for your Civil 3D going forward. It’ll take a little more work when creating the installer, but it’ll be a LOT less work individually installing on each machine :slight_smile:

Can you attach an example drawing?

I just have a generic dwg with a few lines and an xref to test the script. The script is for work so I don’t think I could share that in it’s entirety. Thanks everyone for the suggestions and help. I am production and have no control or input on software deployments so I have to work within what is presented to me. I really appreciate the help, I have the python node to select objects and get them into Dynamo now, which is awesome.

Here is the code fixed for CPython3 (test on Civil2025)

import sys
import clr

# Add Assemblies for AutoCAD and Civil3D
clr.AddReference('AcMgd')
clr.AddReference('AcCoreMgd')
clr.AddReference('AcDbMgd')
clr.AddReference('AecBaseMgd')
clr.AddReference('AecPropDataMgd')
clr.AddReference('AeccDbMgd')

# Import references from AutoCAD
from Autodesk.AutoCAD.Runtime import *
from Autodesk.AutoCAD.ApplicationServices import *
from Autodesk.AutoCAD.EditorInput import *
from Autodesk.AutoCAD.DatabaseServices import *
from Autodesk.AutoCAD.Geometry import *

# Import references from Civil3D
from Autodesk.Civil.ApplicationServices import *
from Autodesk.Civil.DatabaseServices import *

clr.AddReference('AutoCADNodes')
import Autodesk.AutoCAD.DynamoNodes 
from Autodesk.AutoCAD.DynamoNodes import AutoCADUtility

adoc = Application.DocumentManager.MdiActiveDocument
editor = adoc.Editor

        
xrefs = []
blocks =[]

with adoc.LockDocument():
    with adoc.Database as db:
        with db.TransactionManager.StartTransaction() as t:
            
            bt = t.GetObject(db.BlockTableId, OpenMode.ForRead)
            btr = t.GetObject(bt.get_Item(BlockTableRecord.ModelSpace), OpenMode.ForRead)
            for oid in btr:
                bl = t.GetObject(oid, OpenMode.ForRead)
                if isinstance(bl, BlockReference):
                    bd = t.GetObject(bl.BlockTableRecord, OpenMode.ForRead)
                    if bd.IsFromExternalReference:
                       xrefs.append(AutoCADUtility.CreateDynamoObject(bl, False))
                    else:
                       blocks.append(AutoCADUtility.CreateDynamoObject(bl, False))
                        
            
OUT = xrefs, blocks
1 Like

FYI, this node is available as of Civil 3D 2025 and should make this process much easier :slight_smile:

1 Like

Thank You, This is sadly not working for me on Civil3D 2024.

If I wrap in a try-except, it doesn’t like something:

I really wish I could do this in Visual Studio so I could step through the debugger. I’ll be digging through the forums later to see if I can figure out that setup.

Thank You. I really wish I could be up-to-date with the software. I have seen there are a lot of new nodes and I believe API exposures beyond what I have in 2024. I just need to do what I can with the version that the company is providing sadly.

Thanks for all your help BTW, in addition to the help I’ve found in this forum, I have had the Office Hours 29 video open and keep scrolling through it back and forth through all of the progress on my python node attempts thus far.

You can use the method you mentioned instead.

import sys
import clr
import System
# Add Assemblies for AutoCAD and Civil3D
clr.AddReference('AcMgd')
clr.AddReference('AcCoreMgd')
clr.AddReference('AcDbMgd')
clr.AddReference('AecBaseMgd')
clr.AddReference('AecPropDataMgd')
clr.AddReference('AeccDbMgd')

# Import references from AutoCAD
from Autodesk.AutoCAD.Runtime import *
from Autodesk.AutoCAD.ApplicationServices import *
from Autodesk.AutoCAD.EditorInput import *
from Autodesk.AutoCAD.DatabaseServices import *
from Autodesk.AutoCAD.Geometry import *

# Import references from Civil3D
from Autodesk.Civil.ApplicationServices import *
from Autodesk.Civil.DatabaseServices import *

clr.AddReference('AutoCADNodes')
import Autodesk.AutoCAD.DynamoNodes 
from Autodesk.AutoCAD.DynamoNodes import AutoCADUtility
from Autodesk.AutoCAD.DynamoNodes import Object as CADObject

adoc = Application.DocumentManager.MdiActiveDocument
editor = adoc.Editor

        
xrefs = []
blocks =[]

with adoc.LockDocument():
    with adoc.Database as db:
        with db.TransactionManager.StartTransaction() as t:
            
            bt = t.GetObject(db.BlockTableId, OpenMode.ForRead)
            btr = t.GetObject(bt.get_Item(BlockTableRecord.ModelSpace), OpenMode.ForRead)
            for oid in btr:
                bl = t.GetObject(oid, OpenMode.ForRead)
                if isinstance(bl, BlockReference):
                    bd = t.GetObject(bl.BlockTableRecord, OpenMode.ForRead)
                    if bd.IsFromExternalReference:
                       #xrefs.append(AutoCADUtility.CreateDynamoObjectbl, False)) # for Civil 2025+
                       xrefs.append(CADObject.InternalMakeObject(bl, False))
                    else:
                       #blocks.append(AutoCADUtility.CreateDynamoObject(bl, False)) # for Civil 2025+
                       blocks.append(CADObject.InternalMakeObject(bl, False))
                        
            
OUT = xrefs, blocks

Thanks Again. I can get that working in isolation but can’t make it work for what I’m trying to do. This, I believe, cycles through all blocks in model space and checks if each is an xref? I have a list of selected objects and want to check if any of the selected objects are xrefs.

The line “if isinstance(bl, BlockReference):” never recognizes any blocks in the state I have them, which watch nodes tell me is “Autodesk.AutoCAD.DatabaseServices.BlockReference” so I don’t get it. It seems I still need to find the right property or something. I’ll keep going at it. I feel like the answer is right here but I just can’t quite figure it out.