I have a PurgeAll tool which appears to work well, however when used in batch mode the xref layer settings are lost. VISRETAIN remains correctly set. If I run the identical purge code on the current file (ie not using db.ReadDwgFile) then the layers are unaffected. I have tried save/restore LayerState before and after, but again the batch process mangles it, whereas on the current file it all behaves perfectly. This post seems to be closest to a similar problem: http://forums.autodesk.com/t5/NET/VISRETAIN-not-work-with-ReadDwgFile/m-p/3122828/highlight/true#M24... I have included trimmed code below. Many thanks for any thoughts. Dale
<code>
PROCESS:
purgeAllFiles>purgeAll>purgeDictionaries+purgeSymbolTables
CODE:
public static void purgeAllFiles(string pstrSourceFolderName, string pstrTargetFolderName, string pstrTargetFileNameSuffix)
{
Document doc = AcadApp.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
string pathName = pstrSourceFolderName;
string[] fileNames = FolderTools.getFilesInFolder(pstrSourceFolderName, "*.dwg", lsoFolderSearchOption);
foreach (string lstrFileName in fileNames)
{
if (lstrFileName.EndsWith(".dwg", StringComparison.CurrentCultureIgnoreCase))
{
string lstrFileNameOutput = FolderTools.getTargetFileNameFull(pstrTargetFolderName, lstrFileName, pstrTargetFileNameSuffix);
Database db = new Database(false, true);
try
{
db.ReadDwgFile(lstrFileName, FileOpenMode.OpenForReadAndWriteNoShare, true, "");
db.RetainOriginalThumbnailBitmap = true;
string lstrMessage = string.Empty;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
// save Layer State "ATK_PurgeAll"
string lstrLayerStateName = "ATK_PurgeAll";
LayerStateTools.saveLayerStateAllProps(db, tr, lstrLayerStateName);
// this is recursive, no need for extra process
purgeAll(db, tr, true);
// restore Layer State "ATK_PurgeAll"
LayerStateTools.setLayerStateAllProps(db, tr, lstrLayerStateName);
tr.Commit();
}
db.SaveAs(lstrFileNameOutput, true, DwgVersion.Current, db.SecurityParameters);
}
catch (System.Exception ex)
{
ed.WriteMessage("\nProblem");
}
}
}
ed.WriteMessage("\nSuccess");
}
public static bool purgeAll(Database pdb, Transaction ptr, bool pblnSilent)
{
// tables
ObjectIdCollection tableIds = new ObjectIdCollection();
tableIds.Add(pdb.BlockTableId);
tableIds.Add(pdb.DimStyleTableId);
tableIds.Add(pdb.LayerTableId);
tableIds.Add(pdb.LinetypeTableId);
tableIds.Add(pdb.RegAppTableId);
tableIds.Add(pdb.TextStyleTableId);
tableIds.Add(pdb.UcsTableId);
tableIds.Add(pdb.ViewportTableId);
tableIds.Add(pdb.ViewTableId);
// dictionaries
ObjectIdCollection dictIds = new ObjectIdCollection();
dictIds.Add(pdb.MaterialDictionaryId);
dictIds.Add(pdb.MLStyleDictionaryId);
dictIds.Add(pdb.MLeaderStyleDictionaryId);
dictIds.Add(pdb.PlotStyleNameDictionaryId);
dictIds.Add(pdb.TableStyleDictionaryId);
dictIds.Add(pdb.VisualStyleDictionaryId);
// recursive
while (purgeSymbolTables(pdb, ptr, tableIds, pblnSilent) || purgeDictionaries(pdb, ptr, dictIds, pblnSilent))
continue;
return true;
}
public static bool purgeSymbolTables(Database pdb, Transaction ptr, ObjectIdCollection pTableIds, bool pblnSilent)
{
bool itemsPurged = false;
Editor ed = AcadApp.DocumentManager.MdiActiveDocument.Editor;
ObjectIdCollection purgeableIds = new ObjectIdCollection();
foreach (ObjectId id in pTableIds)
{
SymbolTable table = ptr.GetObject(id, OpenMode.ForRead, false) as SymbolTable;
foreach (ObjectId recordId in table)
purgeableIds.Add(recordId);
}
pdb.Purge(purgeableIds);
if (purgeableIds.Count == 0)
return false;
itemsPurged = true;
foreach (ObjectId id in purgeableIds)
{
try
{
SymbolTableRecord record = ptr.GetObject(id, OpenMode.ForWrite) as SymbolTableRecord;
string recordName = record.Name;
record.Erase();
if (!pblnSilent)
{
if (!recordName.Contains("|"))
{
ed.WriteMessage("\nPurging " + record.GetType().Name + " " + recordName);
}
}
}
catch (Autodesk.AutoCAD.Runtime.Exception e)
{
if ((e.ErrorStatus == ErrorStatus.CannotBeErasedByCaller) || (e.ErrorStatus == (ErrorStatus)20072))
itemsPurged = false;
else
throw e;
}
}
return itemsPurged;
}
public static bool purgeDictionaries(Database pdb, Transaction ptr, ObjectIdCollection pDictIds, bool pblnSilent)
{
bool itemsPurged = false;
Editor ed = AcadApp.DocumentManager.MdiActiveDocument.Editor;
ObjectIdCollection purgeableIds = new ObjectIdCollection();
foreach (ObjectId id in pDictIds)
{
DBDictionary dict = ptr.GetObject(id, OpenMode.ForRead, false) as DBDictionary;
foreach (DBDictionaryEntry de in dict)
{
purgeableIds.Add(de.m_value);
}
}
pdb.Purge(purgeableIds);
if (purgeableIds.Count == 0)
return false;
itemsPurged = true;
DBDictionary nod = ptr.GetObject(pdb.NamedObjectsDictionaryId, OpenMode.ForRead) as DBDictionary;
foreach (ObjectId id in purgeableIds)
{
try
{
DBObject obj = ptr.GetObject(id, OpenMode.ForWrite) as DBObject;
obj.Erase();
if (!pblnSilent)
{
foreach (ObjectId dictId in pDictIds)
{
DBDictionary dict = ptr.GetObject(dictId, OpenMode.ForRead, false) as DBDictionary;
string dictName = nod.NameAt(dictId);
if (dict.Contains(id))
{
ed.WriteMessage("\nPurging " + dict.NameAt(id) + " from " + dictName);
break;
}
}
}
}
catch (Autodesk.AutoCAD.Runtime.Exception e)
{
if ((e.ErrorStatus == ErrorStatus.CannotBeErasedByCaller) || (e.ErrorStatus == (ErrorStatus)20072))
itemsPurged = false;
else
throw e;
}
}
return itemsPurged;
}
<code>
In a moment of insight after a sleepless night, it came to me: Resolve the Xrefs before processing
<code>
db.ReadDwgFile(lstrFileName, FileOpenMode.OpenForReadAndWriteNoShare, true, "");
db.RetainOriginalThumbnailBitmap = true;
db.ResolveXrefs(true, false);
<code>
Hope this is helpful for another poor soul.
Dale