Your code is a minimal implementation of a managed version of the 'BURST' express tool command, but the problem is a bit more complicated, and requires checking for things like if a block reference can be exploded (based on its insertion scale factors and the Explodable property of the referenced BlockTableRecord). Since you're not showing all of the code involved (e.g., the code that manages the Transaction), I can't speculate on what the problem may be.
As far as re-inventing the BURST express tool, long ago I built a class that used a TransformOverrule to recursively explode or 'nuke' block references and all nested block references. I was able to easily adapt that code to add the things the BURST command does. I also cleaned up the code and removed dependencies on other code. I'm posting it here mainly to illustrate the problem in all its depth and complexity.
/// BurstOverrule.cs
///
/// ActivistInvestor / Tony T
///
/// Distributed under terms of the MIT license.
/// Adapted from code that performs specialized
/// handling of entities produced by exploding
/// a block reference. This adaptation includes
/// the functionality of the legacy BURST express
/// tool. As written, this code wasn't tested with
/// and may not support fields in attributes.
///
/// Caveat emptor:
///
/// This code was only minimally-tested.
/// Use at your own risk.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using AcRx = Autodesk.AutoCAD.Runtime;
namespace AcMgdLib.DatabaseServices
{
public class BurstOverrule : TransformOverrule
{
RXClass target = RXObject.GetClass(typeof(BlockReference));
bool recursive = false;
int depth = 0;
public BurstOverrule(bool recursive = false)
{
this.recursive = recursive;
AddOverrule(target, this, true);
}
protected override void Dispose(bool disposing)
{
if(disposing && target != null)
{
RemoveOverrule(target, this);
target = null;
}
base.Dispose(disposing);
}
public override void Explode(Entity entity, DBObjectCollection items)
{
try
{
int begin = items.Count;
base.Explode(entity, items);
if(items.Count == begin)
return;
var attdefs = items.OfType<AttributeDefinition>().ToArray();
/// Remove attribute definitions:
foreach(AttributeDefinition attdef in attdefs)
{
items.Remove(attdef);
attdef.Dispose();
}
/// Replace attribute references with text or mtext:
if(entity is BlockReference blockRef)
{
using(var tr = new OpenCloseTransaction())
{
var btr = (BlockTableRecord)tr.GetObject(blockRef.BlockTableRecord, OpenMode.ForRead);
if(btr.Explodable)
{
if(btr.HasAttributeDefinitions)
{
var atts = blockRef.GetAttributes(tr);
foreach(var attref in atts)
{
if(attref.IsMTextAttribute)
{
items.Add((MText)attref.MTextAttribute.Clone());
}
else
{
var text = new DBText();
text.SetDatabaseDefaults(btr.Database);
attref.CopyPropertiesTo(text);
items.Add(text);
}
}
}
if(recursive)
{
var nested = items.OfType<BlockReference>().ToArray();
if(nested.Length > 0)
{
for(int i = 0; i < nested.Length; i++)
{
BlockReference nestedRef = nested[i];
BlockTableRecord nestedBtr = (BlockTableRecord)
tr.GetObject(nestedRef.BlockTableRecord, OpenMode.ForRead);
if(CanExplode(nestedBtr) && nestedRef.ScaleFactors.IsProportional())
{
try
{
++depth;
using(DBObjectCollection nestedResult = new DBObjectCollection())
{
nestedRef.Explode(nestedResult);
items.Remove(nestedRef);
nestedRef.Dispose();
foreach(DBObject obj in nestedResult)
items.Add(obj);
nestedResult.Clear();
}
}
catch(AcRx.Exception ex)
{
DebugOutput.Write(ex.ToString());
}
finally
{
--depth;
}
}
}
}
}
}
tr.Commit();
}
}
}
catch(System.Exception ex)
{
DebugOutput.Write(ex.ToString());
}
}
static bool CanExplode(BlockTableRecord btr)
{
return btr.Explodable &&
!(btr.IsFromExternalReference
|| btr.IsFromOverlayReference
|| btr.IsDependent);
}
}
public static class BurstOverruleExtensions
{
/// <summary>
/// Get AttributeReferences from the given block reference (lazy).
/// Can enumerate AttributeReferences of database resident and
/// non-database resident BlockReferences.
/// </summary>
internal static IEnumerable<AttributeReference> GetAttributes(this BlockReference blkref,
Transaction tr,
OpenMode mode = OpenMode.ForRead,
bool add = true)
{
if(blkref is null)
throw new ArgumentNullException(nameof(blkref));
if(tr is null)
throw new ArgumentNullException(nameof(tr));
var objects = blkref.AttributeCollection.Cast<object>();
object first = objects.FirstOrDefault();
if(first != null)
{
if(first is AttributeReference)
{
foreach(AttributeReference attref in blkref.AttributeCollection)
{
if(add)
tr.AddNewlyCreatedDBObject(attref, true);
yield return attref;
}
}
else
{
foreach(ObjectId id in blkref.AttributeCollection)
if(!id.IsErased)
yield return (AttributeReference)tr.GetObject(id, mode, false, false);
}
}
}
internal static void CopyPropertiesTo(this DBObject source, DBObject dest)
{
if(source is null)
throw new ArgumentNullException(nameof(source));
if(dest is null)
throw new ArgumentNullException(nameof(dest));
if(!dest.IsWriteEnabled)
throw new AcRx.Exception(ErrorStatus.NotOpenForWrite);
Type destType = dest.GetType();
foreach(PropertyDescriptor pd in TypeDescriptor.GetProperties(source))
{
if(!pd.IsReadOnly && pd.ComponentType.IsAssignableFrom(destType))
{
object value = "(null)";
try
{
value = pd.GetValue(source);
if(value != null)
pd.SetValue(dest, value);
else
value = "(null)";
}
catch(AcRx.Exception ex)
{
DebugOutput.Write(
$"Property {pd.Name} = {value.ToString()} threw ErrorStatus.{ex.ErrorStatus}");
}
catch(System.Exception ex)
{
DebugOutput.Write(
$"Property {pd.Name} = {value.ToString()} threw {ex.Message}");
}
}
}
}
}
internal static class DebugOutput
{
[Conditional("DEBUG")]
internal static void Write(string msg)
{
// CopyPropertiesTo() throws many exceptions
// that are mostly-benign. Uncomment this to
// see them on the Console, or just look at
// the debug console.
//Application.DocumentManager.MdiActiveDocument
// .Editor.WriteMessage(msg);
Debug.WriteLine(msg);
}
}
}
Example usage:
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
namespace AcMgdLib.DatabaseServices.Examples
{
public static class TestBurstOverrule
{
[CommandMethod("MGDBURST", CommandFlags.UsePickSet | CommandFlags.Redraw)]
public static void MgdBurstCommand()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
PromptSelectionOptions pso = new PromptSelectionOptions();
pso.RejectObjectsFromNonCurrentSpace = true;
pso.RejectObjectsOnLockedLayers = true;
pso.RejectPaperspaceViewport = true;
var psr = ed.GetSelection(pso);
if(psr.Status != PromptStatus.OK)
return;
ed.InitCommandVersion(2);
using(new BurstOverrule(true))
{
ed.Command("._EXPLODE", psr.Value, "");
}
}
}
}