Getting fatal error access violation when using WblockCloneObjects to clone blocks from another drawing database.

Getting fatal error access violation when using WblockCloneObjects to clone blocks from another drawing database.

ShricharanaB
Advocate Advocate
1,075 Views
6 Replies
Message 1 of 7

Getting fatal error access violation when using WblockCloneObjects to clone blocks from another drawing database.

ShricharanaB
Advocate
Advocate

Hi, 

(ok so I posted this in the wrong forum by mistake. Should be in .NET forum. Don't know how to delete question. Posted the same question in >NET forum.)

I've created a c# .NET plugin for autocad which adds a command. I have has a macro in an excel file which starts autocad and runs the plugin command which gets the input through excel file and then creates what is required.

The plugin needs to import blocks from another drawing and I'm using WblockCloneObjects to do this. 

I've used the same import code till now without any issues. 

When I run the macro through excel I'm randomly getting fatal error access violation error with autocad crashing at WblockCloneObjects line. This happens randomly when starting through excel macro. (Happened only once in debug mode, can't replicate the error again in debug mode.)

I'm using AutoCAD mechanical 2020.

In excel, I've reference AutoCAD 2019 Type Library(can't find for 2020) and AutoCAD Mechanical 2020 Type Library.

 

Can any one please help?

I'm attaching the error details, the import code and application starting code below.

 

Error shown from the dump file:

ShricharanaB_0-1715232811612.png

Call stack:

ShricharanaB_1-1715232865466.png

Full first line in call stack:

> Acdbmgd.dll!Autodesk.AutoCAD.DatabaseServices.Database.WblockCloneObjects(Autodesk.AutoCAD.DatabaseServices.ObjectIdCollection identifiers, Autodesk.AutoCAD.DatabaseServices.ObjectId id, Autodesk.AutoCAD.DatabaseServices.IdMapping mapping, Autodesk.AutoCAD.DatabaseServices.DuplicateRecordCloning cloning, bool deferTranslation) Line 6207 C#

Import Method being used: 

 

 

/// <summary>
/// Checks if given block names exist in given block table and imports all blocks from given drawng if not.
/// </summary>
/// <param name="blockNamesToCheck">Array of block names to check.</param>
/// <param name="drawingPaths">import location of the blocks.</param>
public static void ImportBlocks(string[] blockNamesToCheck, string sourceFileName)
{

    DocumentCollection dm = Application.DocumentManager;
    Editor ed = dm.MdiActiveDocument.Editor;
    Database destDb = dm.MdiActiveDocument.Database;
    Database sourceDb = new Database(false, true);
    //string sourceFileName;
    if (!ShouldImport(destDb, blockNamesToCheck))
    {
        return;
    }
    try
    {
        // Read the DWG into a side database
        sourceDb.ReadDwgFile(sourceFileName, FileOpenMode.OpenForReadAndAllShare, false, null);


        // Create a variable to store the list of block identifiers
        ObjectIdCollection blockIds = new ObjectIdCollection();

        Autodesk.AutoCAD.DatabaseServices.TransactionManager tm = sourceDb.TransactionManager;

        using (Transaction myT = tm.StartTransaction())
        {
            // Open the block table
            BlockTable bt = (BlockTable)tm.GetObject(sourceDb.BlockTableId, OpenMode.ForRead, false);

            // Check each block in the block table
            foreach (ObjectId btrId in bt)
            {
                BlockTableRecord btr = (BlockTableRecord)tm.GetObject(btrId, OpenMode.ForRead, false);

                // Only add named & non-layout blocks to the copy list
                if (!btr.IsAnonymous && !btr.IsLayout) blockIds.Add(btrId);
                btr.Dispose();
            }
        }

        // Copy blocks from source to destination database
        IdMapping mapping = new IdMapping();
        sourceDb.WblockCloneObjects(blockIds, destDb.BlockTableId, mapping, DuplicateRecordCloning.Replace, false);
        // ed.WriteMessage("\nCopied " + blockIds.Count.ToString() + " block definitions from " + sourceFileName + " to the current drawing.");
        ed.WriteMessage("Blocks imported.");


    }
    catch (Autodesk.AutoCAD.Runtime.Exception ex)
    {
        ed.WriteMessage("\nError during copy: " + ex.Message);
        throw new Exception(ex.Message);
    }
    sourceDb.Dispose();
}

 

 

 

VBA code in Excel Macro:

 

 

Dim ACAD As AcadApplication
Dim NewFile As Object
Dim MyAcadPath As String
Dim bReadOnly As Boolean
    
    On Error Resume Next
    Set ACAD = GetObject(, "autocad.Application")
    If (Err <> 0) Then
        Err.Clear
        Set ACAD = CreateObject("autocad.Application")
        If (Err <> 0) Then
            MsgBox "Could Not Load AutoCAD!", vbExclamation
            End
        End If
    End If

    ACAD.Visible = True
    MyAcadPath = "C:\Autodesk\Drawing.dwg"

    bReadOnly = True
    Set NewFile = ACAD.Documents.Open(MyAcadPath, bReadOnly)
    Call CreateInputString
    NewFile.SendCommand cmd

 

 

 

References being used in excel macro

ShricharanaB_2-1715233065254.png

 

I would really appreciate any help.

Thanks in advance!!!

 

 

 

0 Likes
1,076 Views
6 Replies
Replies (6)
Message 2 of 7

daniel_cadext
Advisor
Advisor

wrong forum?

btr.Dispose(); seems incorrect since it's part of the transaction

Python for AutoCAD, Python wrappers for ARX https://github.com/CEXT-Dan/PyRx
0 Likes
Message 3 of 7

ShricharanaB
Advocate
Advocate

Hi,

Thanks for the reply. 

Yeah posted on the wrong forum by mistake.

even if the dispose is left in place, it shouldn't cause any issues right?

 

Tried after removing the btr.Dispose();, AutoCAD still crashes randomly.

 

0 Likes
Message 4 of 7

daniel_cadext
Advisor
Advisor

Lost all my .NET skills lol. I think I would try

sourceDb.closeinput so you know the database is fully read into memory

also I forget if you have to set the source/dest database in mapping

 

Python for AutoCAD, Python wrappers for ARX https://github.com/CEXT-Dan/PyRx
0 Likes
Message 5 of 7

ShricharanaB
Advocate
Advocate

Hi,

Thank you for the suggestion.

I tried adding sourceDB.CloseInput(true) to the code. But AutoCAD is still crashing randomly on WblockCloneObjects line in Database.CS. Particularly this line

Autodesk.AutoCAD.Runtime.Interop.Check((int)_003CModule_003E.AcDbDatabase_002EwblockCloneObjects(GetImpObj(), identifiers.GetImpObj(), (AcDbObjectId*)(&id), mapping.GetImpObj(), (AcDb.DuplicateRecordCloning)cloning, deferTranslation));

This is how I've added the code:

sourceDb.ReadDwgFile(sourceFileName, FileOpenMode.OpenForReadAndAllShare, false, null);
sourceDb.CloseInput(true);

 

 

0 Likes
Message 6 of 7

daniel_cadext
Advisor
Advisor

Can you catch the error message?

Interop.Check should pass up an Arx Acad::ErrorStatus value

 

Python for AutoCAD, Python wrappers for ARX https://github.com/CEXT-Dan/PyRx
0 Likes
Message 7 of 7

ShricharanaB
Advocate
Advocate

The code is within the try - catch block, but it doesn't catch the access violation fatal error I'm getting.  I'm don't know how to use Interop.Check, could you please give me an example? 

0 Likes