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

import blocks -- unhandled access violation reading exception

26 REPLIES 26
Reply
Message 1 of 27
wokeyiyognshenme
950 Views, 26 Replies

import blocks -- unhandled access violation reading exception

civil3d 2018, C#
 
I have a  blocks.dwg . There are 64 block definition in blocks.dwg.
 
I want import all of them into current dwg.
 
sometimes , the code works. 
sometimes , CAD crush:  FAtal error : unhandled access violation reading 0X00F0 exception AT cb3f8b8h !!!!!!!
 
 
private void button_import_block_Click(object sender, EventArgs e)
        {
            Document doc = CADAPP.DocumentManager.MdiActiveDocument;
            Database db = doc.Database; 
 
            using (doc.LockDocument())
            {
                ImportBlocks(db, @"d:\blocks.dwg");
            }
        }
 
 
        public void ImportBlocks(Database destDb, string filename)
        {       
            try
            {
                // Read the DWG into a side database               
               Database sourceDb = new Database(false, true); 
      
                ObjectIdCollection blockIds = new ObjectIdCollection(); 
 
                //The exception is perhaps due to the fact the source dwg is opened.
                //Use FileOpenMode.OpenForReadAndAllShare instead  of System.IO.FileShare.Read
                //sourceDb.ReadDwgFile(filename, System.IO.FileShare.Read, true, "");
                sourceDb.ReadDwgFile(filename, FileOpenMode.OpenForReadAndAllShare, true, "");
 
                sourceDb.CloseInput(true);// make sure the dwg is fully read
 
                // Create a variable to store the list of block identifiers
                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();
                    }
 
                    myT.Commit();
                }
 
                // Copy blocks from source to destination database
                IdMapping mapping = new IdMapping();               
 
                sourceDb.WblockCloneObjects(blockIds, destDb.BlockTableId, mapping, DuplicateRecordCloning.Replace, false);
 
                mapping.Dispose(); 
                sourceDb.Dispose();
            }
            catch (Autodesk.AutoCAD.Runtime.Exception ex)
            {
                this.rtx1.AppendText("error:" + ex.Message + "\n");
            }
 
             
        }
26 REPLIES 26
Message 2 of 27
_gile
in reply to: wokeyiyognshenme

Hi,

 

Try this way:

 

        public static void ImportBlocks(Database destDb, string filename)
        {
            var ids = new ObjectIdCollection();
            using (var sourceDb = new Database(false, true))
            {
                sourceDb.ReadDwgFile(filename, FileOpenMode.OpenForReadAndReadShare, false, null);
                using (var tr = sourceDb.TransactionManager.StartTransaction())
                {
                    var bt = (BlockTable)tr.GetObject(sourceDb.BlockTableId, OpenMode.ForRead);
                    foreach (ObjectId id in bt)
                    {
                        var btr = (BlockTableRecord)tr.GetObject(id, OpenMode.ForRead);
                        if (!btr.IsAnonymous && !btr.IsLayout)
                            ids.Add(id);
                    }
                    tr.Commit();
                }
                var mapping = new IdMapping();
                destDb.WblockCloneObjects(ids, destDb.BlockTableId, mapping, DuplicateRecordCloning.Replace, false);
            }
        }

 

 

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 3 of 27
wokeyiyognshenme
in reply to: _gile

your code doesn't work。

 

private void button8_Click(object sender, EventArgs e)
{
Document doc = CADAPP.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;

using (doc.LockDocument())
{
ImportABC();
}
}

 

 // Error: ePermanentlyErased。

targetDb.WblockCloneObjects(ids, targetDb.BlockTableId, mapping, DuplicateRecordCloning.Replace, false);

Message 4 of 27
_gile
in reply to: wokeyiyognshenme

Could you try it again, I corrected the code.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 5 of 27
wokeyiyognshenme
in reply to: _gile

your code doesn't work.

I try it twice .


first time :
Unhandled Access Violation Reading 0x0170 Exception at CC3F58BFh

second time:
Unhandled Access Violation Reading 0x0128 Exception at CC3F58BFh

private void button10_Click(object sender, EventArgs e)
{
Document doc = CADAPP.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;

using (doc.LockDocument())
{
ImportBlocks_gile(db, @"d:\abclqh.dwg");
}
}

----- following is your code -----
public void ImportBlocks_gile (Database destDb, string filename)
{
var ids = new ObjectIdCollection();
using (var sourceDb = new Database(false, true))
{
sourceDb.ReadDwgFile(filename, FileOpenMode.OpenForReadAndReadShare, false, null);
using (var tr = sourceDb.TransactionManager.StartTransaction())
{
var bt = (BlockTable)tr.GetObject(sourceDb.BlockTableId, OpenMode.ForRead);
foreach (ObjectId id in bt)
{
var btr = (BlockTableRecord)tr.GetObject(id, OpenMode.ForRead);
if (!btr.IsAnonymous && !btr.IsLayout)
ids.Add(id);
}
tr.Commit();
}
var mapping = new IdMapping();
destDb.WblockCloneObjects(ids, destDb.BlockTableId, mapping, DuplicateRecordCloning.Replace, false);
}
}

Message 6 of 27
_gile
in reply to: wokeyiyognshenme

It works for me when calling from this command:

        [CommandMethod("IMPORTBLOCKS")]
        public void Test()
        {
            var db = HostApplicationServices.WorkingDatabase;
            ImportBlocks_gile(db, @"D:\abclqh.dwg");
        }

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 7 of 27
wokeyiyognshenme
in reply to: _gile

did you try my dwg file abclqh.dwg?

Message 8 of 27
wokeyiyognshenme
in reply to: _gile

could you try it in winform ?

Message 9 of 27
_gile
in reply to: wokeyiyognshenme

Do you show your WinForm as modal or modeless dialog?

Could you provide the code you use to show the WinForm?



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 10 of 27
_gile
in reply to: wokeyiyognshenme

I tried with your "abclqh.dwg" file and the 3 following commands (simple command, modal dialog, modeless dialog) an they all worked.

It looks like you have a problem with the access to your "abclqh.dwg" file on your computer.

 

Commands class:

 

using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;

using System;

using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;

namespace ImportBlocksSample
{
    public class Commands
    {
        [CommandMethod("IMPORTBLOCKS")]
        public static void ImportBlocksCommand()
        {
            var doc = AcAp.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            ImportBlocks(db, @"D:\abclqh.dwg");
        }

        [CommandMethod("IMPORTBLOCKSMODALDIALOG")]
        public static void ImportBlocksModalDialog()
        {
            using (var modalDialog = new ImportBlocksDialog())
            {
                AcAp.ShowModalDialog(modalDialog);
            }
        }

        static ImportBlocksDialog modelessDialog;

        [CommandMethod("IMPORTBLOCKSMODELESSDIALOG")]
        public static void ImportBlocksModelessDialog()
        {
            if (modelessDialog == null)
                modelessDialog = new ImportBlocksDialog();
            AcAp.ShowModelessDialog(modelessDialog);
        }

        public static void ImportBlocks(Database destDb, string filename)
        {
            try
            {
                var ids = new ObjectIdCollection();
                using (var sourceDb = new Database(false, true))
                {
                    sourceDb.ReadDwgFile(filename, FileOpenMode.OpenForReadAndAllShare, false, null);
                    using (var tr = sourceDb.TransactionManager.StartTransaction())
                    {
                        var bt = (BlockTable)tr.GetObject(sourceDb.BlockTableId, OpenMode.ForRead);
                        foreach (ObjectId id in bt)
                        {
                            var btr = (BlockTableRecord)tr.GetObject(id, OpenMode.ForRead);
                            if (!btr.IsAnonymous && !btr.IsLayout)
                                ids.Add(id);
                        }
                        tr.Commit();
                    }
                    var mapping = new IdMapping();
                    destDb.WblockCloneObjects(ids, destDb.BlockTableId, mapping, DuplicateRecordCloning.Replace, false);
                }
                AcAp.ShowAlertDialog("Blocks importation succeeded");
            }
            catch(System.Exception ex)
            {
                AcAp.ShowAlertDialog(ex.Message);
            }
        }
    }
}

 

 

ImportBlocksDialog class:

 

using System;
using System.Windows.Forms;

using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;

namespace ImportBlocksSample
{
    public partial class ImportBlocksDialog : Form
    {
        public ImportBlocksDialog()
        {
            InitializeComponent();
        }

        private void ImportButton_Click(object sender, EventArgs e)
        {
            var doc = AcAp.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            using (doc.LockDocument())
            {
                Commands.ImportBlocks(db, @"D:\abclqh.dwg");
            }
            DialogResult = DialogResult.OK; // <- this is to close the form if shown as modal dialog
        }
    }
}

 

 

Note that in case of a modeless dialog it would be safer to directly call the IMPORTBLOCKS command wirh SendStringToExecute (to let AutoCAD take care of locking the document).

 

        private void ImportButton_Click(object sender, EventArgs e)
        {
            var doc = AcAp.DocumentManager.MdiActiveDocument;
            doc.SendStringToExecute("IMPORTBLOCKS\n", false, false, false);
            DialogResult = DialogResult.OK; // <- this is to close the form if shown as modal dialog
        }

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 11 of 27
wokeyiyognshenme
in reply to: _gile

var testForm = new TestForm();

testForm.ShowInTaskbar = true;
testForm.Show();

Message 12 of 27
_gile
in reply to: wokeyiyognshenme

You should not use;

testForm.Show();

to display your dialogs you should use:

Application.ShowModelessDialog(testForm); 

 

See this old but still relevant topic from Kean Walmsley's blog and this other one from the developper's documentation.

 

That said, according you want to use as modeless form, as said upper, you should define a simple command (as the upper IMPORTBLOCKS) and call this method with SendStringToExecute from the button event handler.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 13 of 27
wokeyiyognshenme
in reply to: _gile

I need modalless winform.

 

        static ImportBlocksDialog modelessDialog;

        [CommandMethod("IMPORTBLOCKSMODELESSDIALOG")]
        public static void ImportBlocksModelessDialog()
        {
            if (modelessDialog == null)
                modelessDialog = new ImportBlocksDialog();
            AcAp.ShowModelessDialog(modelessDialog);
        }

 

So I test your code  .

 

start AutoCAD 2019

in cad , i  netload Commands.dll.

in editor, i Enter command:"IMPORTBLOCKSMODELESSDIALOG",

then the ImportBlocksDialog show as modelessDialog.

then click button .

 

first time ,it is ok.

 

then i  Create a new file ,click the button, it's ok.

then i  Create a new file  again,click the button, it's ok.

then i  Create a new file  again,click the button, it's ok.

....after some times....

then i  Create a new file  again,click the button, CAD crush.

 

unhandled access violation reading 0x0108 exception at C9775B8FH

Message 14 of 27
wokeyiyognshenme
in reply to: _gile

 i test the most safer method:

 

        [CommandMethod("IMPORTBLOCKS")]
        public static void ImportBlocksCommand()
        {
            var doc = AcAp.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            ImportBlocks(db, @"D:\abclqh.dwg");
        }

 

i test 30 times.----create 30  new dwg files.

 

all is ok. 

CAD does not crush.

 

But I need modaless winform.

 

 

Message 15 of 27
wokeyiyognshenme
in reply to: _gile

i test the method:

 

doc.SendStringToExecute("IMPORTBLOCKS\n", false, false, false);

 

using System;
using System.Windows.Forms;

using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;

namespace ImportBlocksSample
{
    public partial class ImportBlocksDialog : Form
    {
        public ImportBlocksDialog()
        {
            InitializeComponent();
        }
 
        private void ImportButton_Click(object sender, EventArgs e)
        {
            var doc = AcAp.DocumentManager.MdiActiveDocument;
            doc.SendStringToExecute("IMPORTBLOCKS\n", false, false, false);
            DialogResult = DialogResult.OK; // <- this is to close the form if shown as modal dialog
        }
    }
}


using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;

using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;

namespace ImportBlocksSample
{
    public class Commands
    {
        static ImportBlocksDialog modelessDialog;

        [CommandMethod("IMPORTBLOCKSMODELESSDIALOG")]
        public static void ImportBlocksModelessDialog()
        {
            if (modelessDialog == null)
                modelessDialog = new ImportBlocksDialog();
            AcAp.ShowModelessDialog(modelessDialog);
        }

        public static void ImportBlocks(Database destDb, string filename)
        {
            try
            {
                var ids = new ObjectIdCollection();
                using (var sourceDb = new Database(false, true))
                {
                    sourceDb.ReadDwgFile(filename, FileOpenMode.OpenForReadAndAllShare, false, null);
                    using (var tr = sourceDb.TransactionManager.StartTransaction())
                    {
                        var bt = (BlockTable)tr.GetObject(sourceDb.BlockTableId, OpenMode.ForRead);
                        foreach (ObjectId id in bt)
                        {
                            var btr = (BlockTableRecord)tr.GetObject(id, OpenMode.ForRead);
                            if (!btr.IsAnonymous && !btr.IsLayout)
                                ids.Add(id);
                        }
                        tr.Commit();
                    }
                    var mapping = new IdMapping();
                    destDb.WblockCloneObjects(ids, destDb.BlockTableId, mapping, DuplicateRecordCloning.Replace, false);
                }
                AcAp.ShowAlertDialog("Blocks importation succeeded");
            }
            catch (System.Exception ex)
            {
                AcAp.ShowAlertDialog(ex.Message);
            }
        }
    }
}

 

first time ,it is ok

 

second time ,create a new dwg file ,click the button ,it is ok

 

after several time ---- about 10 times

 

CAD crush

 

 unhandled access violation reading 0x0100 exception at C9775B8FH

Message 16 of 27
_gile
in reply to: wokeyiyognshenme

Difficult to diagnose.

Perhaps you read the source DWG many times too quickly.

Try to force a garbage collection after the newly created Database is disposed.

 

        public static void ImportBlocks(Database destDb, string filename)
        {
            try
            {
                var ids = new ObjectIdCollection();
                using (var sourceDb = new Database(false, true))
                {
                    sourceDb.ReadDwgFile(filename, FileOpenMode.OpenForReadAndAllShare, false, null);
                    using (var tr = sourceDb.TransactionManager.StartTransaction())
                    {
                        var bt = (BlockTable)tr.GetObject(sourceDb.BlockTableId, OpenMode.ForRead);
                        foreach (ObjectId id in bt)
                        {
                            var btr = (BlockTableRecord)tr.GetObject(id, OpenMode.ForRead);
                            if (!btr.IsAnonymous && !btr.IsLayout)
                                ids.Add(id);
                        }
                        tr.Commit();
                    }
                    var mapping = new IdMapping();
                    destDb.WblockCloneObjects(ids, destDb.BlockTableId, mapping, DuplicateRecordCloning.Replace, false);
                }
                GC.Collect(); // <- forces a garbage collection
                AcAp.ShowAlertDialog("Blocks importation succeeded");
            }
            catch(System.Exception ex)
            {
                AcAp.ShowAlertDialog(ex.Message);
            }
        }

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 17 of 27
wokeyiyognshenme
in reply to: _gile

I try the following code .

 

        private void ImportButton_Click(object sender, EventArgs e)
        {
            rtx1.Clear();

            var doc = AcAp.DocumentManager.MdiActiveDocument;
            var db = doc.Database;

            var listname = Commands.ImportBlocks_listname(@"D:\abclqh.dwg");
            foreach (var item in listname)
            {
                rtx1.AppendText(item + hh);
            }
            rtx1.AppendText("---" + hh);

            foreach (var name in listname)
            {
                rtx1.AppendText("-- read --" + name +  hh);  

                using (doc.LockDocument())
                {
                    Commands.only_sourceDb_ReadDwgFile(  @"D:\abclqh.dwg" );
                }
            }

            rtx1.AppendText("----all ok-----" + hh); 
        }

public static List<string> ImportBlocks_listname(string filename)
        {
            List<string> listName = new List<string>();
            try
            {
                var ids = new ObjectIdCollection();
                using (var sourceDb = new Database(false, true))
                {
                    sourceDb.ReadDwgFile(filename, FileOpenMode.OpenForReadAndAllShare, false, null);
                    using (var tr = sourceDb.TransactionManager.StartTransaction())
                    {
                        var bt = (BlockTable)tr.GetObject(sourceDb.BlockTableId, OpenMode.ForRead);

                        foreach (ObjectId id in bt)
                        {
                            var btr = (BlockTableRecord)tr.GetObject(id, OpenMode.ForRead);
                            if (!btr.IsAnonymous && !btr.IsLayout)
                            {
                                listName.Add(btr.Name);
                            }
                        }
                        tr.Commit();
                    }                     
                }
                AcAp.ShowAlertDialog("get List name OK");
            }
            catch (System.Exception ex)
            {
                AcAp.ShowAlertDialog(ex.Message);
            }

            return listName;
        }

        public static void only_sourceDb_ReadDwgFile(string filename )
        {
            try
            {    
                using (var sourceDb = new Database(false, true))
                {
                    sourceDb.ReadDwgFile(filename, FileOpenMode.OpenForReadAndAllShare, false, null);
                    using (var tr = sourceDb.TransactionManager.StartTransaction())
                    {
                        var bt = (BlockTable)tr.GetObject(sourceDb.BlockTableId, OpenMode.ForRead);     
                        tr.Commit();
                    } 
                }              
            }
            catch (System.Exception ex)
            {
                AcAp.ShowAlertDialog(ex.Message);
            }
        }

 

1、 first dwg , it is ok .

 

2 、create a new dwg file ,and click the button .  it's ok

3 、create a new dwg file ,and click the button .  windows 10 crush, pop up a window : not enough memory.

 

i restart my computer.Try again.

my computer memory is  16GB.

 

1、 first dwg , it is ok .

but i find that ,in the windows 10 Task Manager,  the 16GB is nearly full

 

2. second time ,CAD Crush.

 

so , i think ,  using (var sourceDb = new Database(false, true))  don't really dispose the sourceDb , don't realy release the memory.

 

 

 

Message 18 of 27
_gile
in reply to: wokeyiyognshenme


@wokeyiyognshenme  a écrit :

so , i think ,  using (var sourceDb = new Database(false, true))  don't really dispose the sourceDb , don't realy release the memory.


Look at my last reply about garbage collection.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 19 of 27
wokeyiyognshenme
in reply to: _gile

first dwg ,it is ok, but computer memory still  quickly become full.  gc.collect()  doesn't work.

 

then create a new dwg , click the buton , after a few seconds , CAD crush.

 

        public static void only_sourceDb_ReadDwgFile(string filename )
        {
            try
            {    
                using (var sourceDb = new Database(false, true))
                {
                    sourceDb.ReadDwgFile(filename, FileOpenMode.OpenForReadAndAllShare, false, null);
                    sourceDb.CloseInput(true);
                    using (var tr = sourceDb.TransactionManager.StartTransaction())
                    {
                        var bt = (BlockTable)tr.GetObject(sourceDb.BlockTableId, OpenMode.ForRead);     
                        tr.Commit();
                    } 
                }

                GC.Collect(); // <- forces a garbage collection

            }
            catch (System.Exception ex)
            {
                AcAp.ShowAlertDialog(ex.Message);
            }
        } 

 

Message 20 of 27
wokeyiyognshenme
in reply to: _gile

sourceDb.CloseInput(true);// try it

GC.Collect(); // <- forces a garbage collection

 

both doesn't work.

 

 public static void only_sourceDb_ReadDwgFile(string filename )
        {
            try
            {    
                using (var sourceDb = new Database(false, true))
                {
                    sourceDb.ReadDwgFile(filename, FileOpenMode.OpenForReadAndAllShare, false, null);

                    sourceDb.CloseInput(true);// try it 

                    using (var tr = sourceDb.TransactionManager.StartTransaction())
                    {
                        var bt = (BlockTable)tr.GetObject(sourceDb.BlockTableId, OpenMode.ForRead);     
                        tr.Commit();
                    } 
                }

                GC.Collect(); // <- forces a garbage collection

            }
            catch (System.Exception ex)
            {
                AcAp.ShowAlertDialog(ex.Message);
            }
        } 


        private void ImportButton_Click(object sender, EventArgs e)
        {
            rtx1.Clear();

            var doc = AcAp.DocumentManager.MdiActiveDocument;

            for (int i = 0; i < 60; i++)
            {
                rtx1.AppendText("-- i --" + i + hh);

                using (doc.LockDocument())
                {
                    Commands.only_sourceDb_ReadDwgFile(@"D:\abclqh.dwg");
                }
            } 

            rtx1.AppendText("----all ok-----" + hh);            
        }

 

 

full memory.jpg 

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

Post to forums  

Forma Design Contest


AutoCAD Beta