# .Net WblockCloneObjects please help

**URL:** <https://forum.dynamobim.com/t/net-wblockcloneobjects-please-help/94234>\
**Category:** Civil 3D\
**Tags:** python\
**Created:** [October 3, 2023, 7:52am UTC](https://forum.dynamobim.com/t/net-wblockcloneobjects-please-help/94234 "2023-10-03T07:52:30Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![kbzawork](https://avatars.discourse-cdn.com/v4/letter/k/d26b3c/32.png) [@kbzawork](https://forum.dynamobim.com/u/kbzawork)\
**Post date:** [October 3, 2023, 7:52am UTC](https://forum.dynamobim.com/t/net-wblockcloneobjects-please-help/94234/1 "2023-10-03T07:52:30Z")

</div>

Hi …  
This portion of code with C# does the copy between databases without error …

```auto
var mapping = new IdMapping();
using (var sourceDb = new Database(false, true))
{
    sourceDb.ReadDwgFile(xrpath, FileOpenMode.OpenForReadAndAllShare, true, "");
    ObjectId xrMsId = SymbolUtilityServices.GetBlockModelSpaceId(sourceDb);
    var ids = new ObjectIdCollection();
    using (var tr = new OpenCloseTransaction())
    {
        BlockTableRecord xrMS = (BlockTableRecord)tr.GetObject(xrMsId, OpenMode.ForWrite);
        foreach (ObjectId id in xrMS)
        {
            Entity ent = (Entity)tr.GetObject(id, OpenMode.ForWrite);
            ent.TransformBy(EM);
            if (msg1.Contains(ent.Layer))
                ids.Add(id);
        }
    }
    var db = doc.Database;
    ObjectId MsId = SymbolUtilityServices.GetBlockModelSpaceId(db);
    sourceDb.WblockCloneObjects(ids, MsId, mapping, DuplicateRecordCloning.Ignore, false);
}

```

Here’s my attempt using python script in Dynamo…

```auto
# Load the Python Standard and DesignScript Libraries
import sys
import clr
import fnmatch

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

# axtra for ReadDwgFile
from System.IO import FileShare

# 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 *

bn = IN[1] #example: "TAN"
LF = IN[2] #exxample: "ZONE*H*"

# missing ... user select nested enttity for the transform matrix

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

xrefGraph = adoc.Database.GetHostDwgXrefGraph(True)
xrefNode = xrefGraph.GetXrefNode(bn)
xrpath = ""

with OpenCloseTransaction() as tr:
    xrbr = tr.GetObject(xrefNode.BlockTableRecordId, OpenMode.ForRead)
    xrpath = xrbr.GetXrefDatabase(False).Filename

ids = ObjectIdCollection()

with Database(False, True) as db:
    db.ReadDwgFile(xrpath, FileShare.ReadWrite, False, "")
    xrMsId = SymbolUtilityServices.GetBlockModelSpaceId(db);
    with OpenCloseTransaction() as tr:
        xrMS = tr.GetObject(xrMsId, OpenMode.ForWrite)
        for id in xrMS:
            try:
                ent = tr.GetObject(id, OpenMode.ForWrite)
                if fnmatch.fnmatch(ent.Layer,LF):
                    # ent.TransformBy(EM);
                    ids.Add(id)
            except:
                continue
        #
        #mapping = IdMapping()
        #MsId = SymbolUtilityServices.GetBlockModelSpaceId(adoc.Database)
        #db.WblockCloneObjects(ids, MsId, mapping, DuplicateRecordCloning.Ignore, False)
        #
        #with adoc.LockDocument():
        # with adoc.Database as docdb:
        # with docdb.TransactionManager.StartTransaction() as t: 
        # mapping = IdMapping()        
        # MsId = SymbolUtilityServices.GetBlockModelSpaceId(docdb)
        # ms = t.GetObject(MsId,OpenMode.ForWrite)
        # db.WblockCloneObjects(ids, MsId, mapping, DuplicateRecordCloning.Ignore, False)
        # t.Commit()
        

OUT = ids

```

These lines result in Lock Violation error …

```auto
        mapping = IdMapping()
        MsId = SymbolUtilityServices.GetBlockModelSpaceId(adoc.Database)
        db.WblockCloneObjects(ids, MsId, mapping, DuplicateRecordCloning.Ignore, False)

```

And these lines result in error … was not open for write …

```auto
        with adoc.LockDocument():
            with adoc.Database as docdb:
                with docdb.TransactionManager.StartTransaction() as t: 
                    mapping = IdMapping()        
                    MsId = SymbolUtilityServices.GetBlockModelSpaceId(docdb)
                    ms = t.GetObject(MsId,OpenMode.ForWrite)
                    db.WblockCloneObjects(ids, MsId, mapping, DuplicateRecordCloning.Ignore, False)
                    t.Commit()

```

? I have something the wrong way around ?

---

<div class="post-metadata">

**Author:** ![Mike.Buttery](https://avatars.discourse-cdn.com/v4/letter/m/b19c9b/32.png) [@Mike.Buttery](https://forum.dynamobim.com/u/Mike.Buttery)\
**Post date:** [October 11, 2023, 2:23am UTC](https://forum.dynamobim.com/t/net-wblockcloneobjects-please-help/94234/2 "2023-10-11T02:23:40Z")

</div>

Here are a few pointers to help clean up your code and get it working

With AutoCAD all actions on the document should be inside a transaction with a locked document  
Following lines are outside the transaction

```python
xrefGraph = adoc.Database.GetHostDwgXrefGraph(True)
xrefNode = xrefGraph.GetXrefNode(bn)
xrpath = ""

```

You also use the `with OpenCloseTransaction() as tr:` I have not used this class as typically a transaction is called on a particular database object. If you make any changes to the database a `tr.Commit()` should be called

In python the `with` statement is used to encapsulate code for cleaner execution as it automatically tries to clean up memory at completion. Nesting here is important. This line `ids = ObjectIdCollection()` brings the nesting back to the left and effectively closes the prior `with` statement so your transaction is now closed

Next you are trying to “side load” the xref database for _Tan_ and transform all objects on layer(s) that match _ZONE\*H\*_. Note minor typo with a semi-colon at end of line 49

The python library `fnmatch` is for Unix filename matching and although it does work you could use string methods `if ent.Layer.startswith("ZONE") and "H" in ent.Layer:` or a regular expression `if re.fullmatch("^ZONE.*H.*$", ent.Layer):`

You will have to save the side loaded xref database for the changes to be permanent

I would look at Kean’s C# code for clues how to do this here → [Modifying the contents of an AutoCAD xref using .NET](https://www.keanw.com/2015/01/modifying-the-contents-of-an-autocad-xref-using-net.html)

---

<div class="post-metadata">

**Author:** ![kbzawork](https://avatars.discourse-cdn.com/v4/letter/k/d26b3c/32.png) [@kbzawork](https://forum.dynamobim.com/u/kbzawork)\
**Post date:** [October 12, 2023, 9:47am UTC](https://forum.dynamobim.com/t/net-wblockcloneobjects-please-help/94234/3 "2023-10-12T09:47:52Z")

</div>

Silly Me!!! It’s working now! … very first sentence … With AutoCAD all actions on the document should be inside a transaction with a locked document … that solved it …  
Thank You!!!
