Hi Community,
I'm developing a plugin for autocad in c# and I'm facing a problem while trying to insert some blocks in autocad. The exception thrown from autocad is:
"INTERNAL ERROR: !dbinsert.cpp@858: eNoDatabase".
This exception occure sporadically, so I can't always reproduce it when I debug for example. Is there any way to catch/handle this exception ?
I'm catching all System.Exceptions and Autocad Runtime Exception but without success.. 😞
Thank you all in advance.
itmtha01.
Hi mzakiralam,
thank your for your prompt reply my code is a bit complicated. I have tried to simplify the logic as below:
public void AddBlocksToDrawing()
{
try
{
Document doc = acad_App.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
DocumentBroker broker = DocumentBroker.GetInstance();
LinkedList<BlockReference> legendLines = broker.GetLegendLines(doc);
using (DocumentLock docLock = doc.LockDocument())
{
using (Transaction trans = db.TransactionManager.StartTransaction())
{
BlockTable bt = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead);
BlockTableRecord btr = (BlockTableRecord)trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead);
ExplodeNestedBlocks(db, trans);
ClearOldBlocks(trans, btr);
try
{
UpdateSymbolIndex(updateSymbols, btr, trans);
Point3d pos = new Point3d(0.0, 0.0, 0.0);
foreach (string category in this.categories)
{
List<string> subCategories = new List<string>();
subCategories = GetSubCategories(category, btr, trans);
foreach (string subCategory in subCategories)
{
if (doc == null || db == null)
{
MessageDialog.Show("Error", "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
return;
}
List<BlockReference> allSymbols = GetAllSubCatSymbols(category, btr, trans);
List<BlockReference> symbols = GetAllSubCatSymbols(category, btr, trans);
pos = AddNewBlock(pos,"block1", trans);
foreach (BlockReference symbol in this.bars)
{
string count = CountSymbol(symbol, allSymbols);
pos = AddBlockLine(symbol, pos, trans);
}
foreach (BlockReference symbol in this.symbols)
{
string count = CountSymbol(symbol, allSymbols);
pos = AddBlockLine(symbol, pos, trans,);
}
pos = AddNewBlock(pos, ,"block2", trans);
}
pos = AddNewBlock(pos, ,"block3", trans);
}
AddNewBlock(pos,,"block4", trans);
UpdateAttributes(btr, trans);
}
catch (System.Exception ex)
{
MessageDialog.Show("Error"+ ex.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
}
btr.Close();
bt.Close();
trans.Commit();
}
}
}
catch (System.Exception ex)
{
MessageDialog.Show(ex.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
public void ExplodeNestedBlocks(Database db, Transaction trans)
{
BlockTable bt = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead);
BlockTableRecord btr = (BlockTableRecord)trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead);
foreach (ObjectId id in btr)
{
BlockReference itemBlock = trans.GetObject(id, OpenMode.ForWrite) as BlockReference;
if (itemBlock != null && bla..)
{
BlockTableRecord nestedBtr = itemBlock.BlockTableRecord.GetObject(OpenMode.ForRead) as BlockTableRecord;
foreach (ObjectId objId in nestedBtr)
{
BlockReference nestedItemBlock = trans.GetObject(objId, OpenMode.ForRead) as BlockReference;
if (nestedItemBlock != null)
{
try
{
itemBlock.ExplodeToOwnerSpace();
itemBlock.Erase(true);
}
catch (System.Exception ex)
{
MessageDialog.Show("Error", "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
return;
}
}
}
}
}
}
}
private void ClearOldBlocks(Transaction trans, BlockTableRecord btr)
{
foreach (ObjectId id in btr)
{
BlockReference itemBlock = trans.GetObject(id, OpenMode.ForRead) as BlockReference;
if (itemBlock != null)
{
AttributeDefinition symbolType = AttributeUtil.GetAttributeDefinition(itemBlock, Const.TYPE);
if (bla..)
{
trans.GetObject(id, OpenMode.ForWrite).Erase();
}
}
}
}
private void UpdateSymbolIndex(Dictionary<string, int> updateSymbols, BlockTableRecord btr, Transaction trans)
{
foreach (ObjectId id in btr)
{
BlockReference itemBlock = trans.GetObject(id, OpenMode.ForRead) as BlockReference;
if (itemBlock != null)
{
AttributeDefinition attrType = AttributeUtil.GetAttributeDefinition(itemBlock, Const.TYPE);
String symbolPrefix = AttributeUtil.GetConfigVar(Const.SYMBOL_PREFIX);
if (bla..)
{
try
{
string newIndex = "X";
BlockTableRecord srcBtr = trans.GetObject(itemBlock.BlockTableRecord, OpenMode.ForRead) as BlockTableRecord;
foreach (ObjectId sID in srcBtr)
{
MText mtext = trans.GetObject(sID, OpenMode.ForWrite) as MText;
if (mtext != null)
{
string content = mtext.Contents;
mtext.Contents = content + newIndex;
mtext.Close();
break;
}
}
srcBtr.Close();
}
catch (System.Exception ex)
{
MessageDialog.Show("Ein Fehler ist aufgetreten:" + Const.NEW_LINE + ex.ToString(), "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
return;
}
}
}
}
}
private Point3d AddNewBlock(Point3d pos, String blockname, Transaction trans)
{
try
{
BlockReference newBlock = InsertBlockReference("Legend_"+blockname, blockname, new Point3d(0.0, 0.0, 0.0), trans);
try
{
double[] posData = GetProjDataPos();
newBlock.Position = new Point3d(posData[0], posData[1], 0.0);
Extents3d extents = newBlock.GeometricExtents;
double height = Math.Abs(extents.MaxPoint.Y - extents.MinPoint.Y);
pos = new Point3d(newBlock.Position.X, newBlock.Position.Y + height, 0.0);
}
catch (System.Exception ex)
{
MessageDialog.Show("Position konnte nicht ermittelt werden. " + ex.ToString(), "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
return pos;
}
}
}
catch (System.Exception ex)
{
MessageDialog.Show("Ein Fehler ist aufgetreten:" + Const.NEW_LINE + ex.ToString(), "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
return pos;
}
return pos;
}
private BlockReference InsertBlockReference(string blockName, string templateName, Point3d position, Transaction trans)
{
string inputFile = string.Empty;
try
{
inputFile = Path.Combine(Const.TEMPLATE_PATH, templateName + ".dwg");
}
catch (System.Exception)
{
throw new System.Exception("Der angegebene Pfad wurde nicht gefunden.");
}
Document currentFileDoc = acad_App.DocumentManager.MdiActiveDocument;
Database currentFileDB = currentFileDoc.Database;
Database inputFileDB = new Database(false, true);
try
{
inputFileDB.ReadDwgFile(inputFile, FileOpenMode.OpenForReadAndReadShare, false, null);
}
catch (System.Exception)
{
throw new System.Exception("Die Eingabedatei existiert nicht oder ist nicht verfügbar: " + inputFile);
}
BlockTable bt = (BlockTable)trans.GetObject(currentFileDB.BlockTableId, OpenMode.ForRead);
BlockTableRecord btr = (BlockTableRecord)trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
ObjectId objId = currentFileDB.Insert(blockName, inputFileDB, true);
BlockReference newBlock = new BlockReference(position, objId);
btr.AppendEntity(newBlock);
trans.AddNewlyCreatedDBObject(newBlock, true);
return newBlock;
}
private List<string> GetSubCategories(string category, BlockTableRecord btr, Transaction trans)
{
List<string> subCategories = new List<string>();
foreach (ObjectId id in btr)
{
BlockReference itemBlock = trans.GetObject(id, OpenMode.ForRead) as BlockReference;
if (itemBlock != null)
{
if (bla..)
{
try
{
Dictionary<string, string> attrValues = AttributeUtil.GetAllAttributes(itemBlock);
if (bla..)
{
subCategories.Add(subCategory);
}
}
catch (System.Exception ex)
{
MessageDialog.Show("Ein Fehler ist aufgetreten:" + Const.NEW_LINE + ex.ToString(), "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
return null;
}
}
}
}
return subCategories;
}
private List<BlockReference> GetAllSubCatSymbols(string category, string subCatetory, BlockTableRecord btr, Transaction trans)
{
List<BlockReference> symbols = new List<BlockReference>();
foreach (ObjectId id in btr)
{
BlockReference itemBlock = trans.GetObject(id, OpenMode.ForRead) as BlockReference;
if (itemBlock != null)
{
try
{
if (bla...)
{
symbols.Add(itemBlock);
}
}
catch (System.Exception ex)
{
MessageDialog.Show("Ein Fehler ist aufgetreten:" + Const.NEW_LINE + ex.ToString(), "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
return null;
}
}
}
return symbols;
}
private void AddBlockLine(BlockReferencwe symbol, Point3d position, Transaction trans))
{
.
.
.
.
BlockReference newBlock = InsertBlockReference("LegendLine", "template2",position, trans);
CopySymbol(symbol,newBlock, trans);
}
private void UpdateAttributes(BlockTableRecord btr, Transaction trans)
{
foreach (ObjectId id in btr)
{
BlockReference itemBlock = trans.GetObject(id, OpenMode.ForRead) as BlockReference;
if (itemBlock != null)
{
if (bla..)
{
AttributeUtil.SetAttribute(itemBlock, "ATT1", "0", trans);
AttributeUtil.SetAttribute(itemBlock, "ATT2", "0", trans);
AttributeUtil.SetAttribute(itemBlock, "ATT3", "0", trans);
AttributeUtil.SetAttribute(itemBlock, "ATT4", "0", trans);
}
}
}
}
public static void SetAttribute(BlockReference block, string attrTag, string attrValue, Transaction trans)
{
if (!string.IsNullOrEmpty(attrTag) && !string.IsNullOrEmpty(attrValue))
{
try
{
block.UpgradeOpen();
}
catch { }
AttributeDefinition attrDe = AttributeUtil.GetAttributeDefinition(block, attrTag);
if (attrDe != null)
{
if (!attrDe.Constant)
{
AttributeReference attrRe = AttributeUtil.GetAttribute(block, attrTag);
if (attrRe != null)
attrRe.TextString = attrValue;
else
{
using (attrRe = new AttributeReference())
{
attrRe.SetAttributeFromBlock(attrDe, block.BlockTransform);
attrRe.Visible = attrDe.Visible;
Point3d basePoint = attrDe.Position;
basePoint += block.Position.GetAsVector();
attrRe.Position = basePoint;
attrRe.Height = attrDe.Height;
attrRe.Rotation = attrDe.Rotation;
attrRe.FieldLength = attrDe.FieldLength;
if (attrDe.IsMTextAttributeDefinition)
{
attrRe.IsMTextAttribute = true;
attrRe.TextString = attrValue;
attrRe.UpdateMTextAttribute();
}
else
attrRe.TextString = attrValue;
block.AttributeCollection.AppendAttribute(attrRe);
trans.AddNewlyCreatedDBObject(attrRe, true);
}
}
}
}
}
}
private void CopySymbol(BlockReference symbol, BlockReference dstBlock, Transaction trans)
{
BlockTableRecord dstBtr = trans.GetObject(dstBlock.BlockTableRecord, OpenMode.ForWrite) as BlockTableRecord;
BlockReference copy = (BlockReference)symbol.Clone();
AttributeDefinition attrSymbolPos = AttributeUtil.GetAttributeDefinition(dstBlock, Const.SYMBOLPOS);
if (attrSymbolPos == null)
{
throw new System.Exception("Fehler: Symbolposition ist nicht definiert.");
}
copy.Position = attrSymbolPos.Position;
dstBtr.AppendEntity(copy);
trans.AddNewlyCreatedDBObject(copy, true);
}
Thank you in advance !!!
itmtha01.
Hi again,
after debuging I've noticed that the exception occured in the method: InsertBlockReference() while calling the Insert method below:
ObjectId objId = currentFileDB.Insert(blockName, inputFileDB, true);
Can I make any check before trying to insert a template ??
Best regards.
sorry for late reply. I have skimmed through your code. It seems like that you want to insert some block from an external drawing into current drawing. Am I correct? you have opened database without opening the drawing. then you did not extract those block from that database and you try to insert that into current database which is not found and throw an exception. If what I have understood is correct then have a close look into below links which may serve your purpose
http://adndevblog.typepad.com/autocad/2012/05/insert-block-from-a-different-dwg-using-net-.html
Or kindly explain if I thought wrong.
Please modify the line:
inputFileDB.ReadDwgFile(inputFile, FileOpenMode.OpenForReadAndReadShare, false, null);
Modifiy the above line in your code with below modification, from false to true
inputFileDB.ReadDwgFile(inputFile,System.IO.FileShare.ReadWrite, true, "");
Hi mzakiralam,
thank your for your reply. you're right I'm inserting some blocks from external drawings into my current drawing. I've replaced the line:
inputFileDB.ReadDwgFile(inputFile, FileOpenMode.OpenForReadAndReadShare, false, null);
like you said with this:
inputFileDB.ReadDwgFile(inputFile,System.IO.FileShare.ReadWrite, true, "");
But unfortunately the exception still comes from time to time.
I will try now your proposed method WblockCloneObjects(). Can I get the cloned Object (my new Blockreference) back ? I want to set some attributes after copying it.
Best regards.
itmtha01.
Hi,
sorry that did not work for you. I think the problem is you have added that block reference and return it which is not commited yet. I am not sure, just guess, as I am not so expert. I think jeff want to indicate something like that. Can you just use a sub instead of returning the blockreference? I have done something like that and it works for me. Afterwards you can find properties of that block easily. I have done something like below. sorry the code is in VB
<CommandMethod("IBLK")> Public Sub InsertBLockfromOutside() Dim doc As Document = Application.DocumentManager.MdiActiveDocument Dim db As Database = doc.Database Dim ed As Editor = doc.Editor Dim blockname As String = "TestBLK" Dim drawingPath As String = "C:\Users\alamzaki\Desktop\Test_data\PG-VSON-4-1_afattintel_test.dwg" Dim blkPos As Point3d = New Point3d(0, 0, 0) Try Using tx As Transaction = db.TransactionManager.StartTransaction() Dim bt As BlockTable = tx.GetObject(db.BlockTableId, OpenMode.ForRead) Dim ms As BlockTableRecord = tx.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite) If Not bt.Has(blockname) Then InsertBlock(blockname, drawingPath, blkPos, db, ms, tx) End If tx.Commit() End Using Catch ex As System.Exception MsgBox(ex.Message) End Try End Sub Public Sub InsertBlock(blkName As String, dwgPath As String, positon As Point3d, acDb As Database, btr As BlockTableRecord, trans As Transaction) Dim dbdwg As Database = New Database(False, True) dbdwg.ReadDwgFile(dwgPath, FileOpenMode.OpenForReadAndAllShare, True, "") Dim id As ObjectId = acDb.Insert(blkName, dbdwg, True) dbdwg.Dispose() Dim blkRef As New BlockReference(positon, id) btr.AppendEntity(blkRef) trans.AddNewlyCreatedDBObject(blkRef, True) End Sub
I have also tried with function mode and it is working as well for me.
<CommandMethod("IBLK")> Public Sub InsertBLockfromOutside() Dim doc As Document = Application.DocumentManager.MdiActiveDocument Dim db As Database = doc.Database Dim ed As Editor = doc.Editor Dim blockname As String = "TestBLK" Dim drawingPath As String = "C:\Users\alamzaki\Desktop\Test_data\PG-VSON-4-1_afattintel_test.dwg" Dim blkPos As Point3d = New Point3d(0, 0, 0) Try Using tx As Transaction = db.TransactionManager.StartTransaction() Dim bt As BlockTable = tx.GetObject(db.BlockTableId, OpenMode.ForRead) Dim ms As BlockTableRecord = tx.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite) If Not bt.Has(blockname) Then 'InsertBlock(blockname, drawingPath, blkPos, db, ms, tx) Dim br As BlockReference = InsertBlock1(blockname, drawingPath, blkPos, db, ms, tx) MsgBox(br.Name) End If tx.Commit() End Using Catch ex As System.Exception MsgBox(ex.Message) End Try End Sub Public Function InsertBlock1(blkName As String, dwgPath As String, positon As Point3d, acDb As Database, btr As BlockTableRecord, trans As Transaction) As BlockReference Dim dbdwg As Database = New Database(False, True) dbdwg.ReadDwgFile(dwgPath, FileOpenMode.OpenForReadAndAllShare, True, "") Dim id As ObjectId = acDb.Insert(blkName, dbdwg, True) dbdwg.Dispose() Dim blkRef As New BlockReference(positon, id) btr.AppendEntity(blkRef) trans.AddNewlyCreatedDBObject(blkRef, True) Return blkRef End Function