According to the tests I made, an opened dwg (in the current session or another) has an Archive attribute.
So, I rewrote my batch method to work only with the active document or closed files and I try to cath exceptions as GlennR shows
here (thanks to him).
Here's where I am now. I tried to make a more 'generic' method using a delegate.
using System.IO;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using acadApp = Autodesk.AutoCAD.ApplicationServices.Application;
namespace BatchProcess
{
public class Process
{
public delegate void ProcessDatabase(Database db);
public static void ProcessFiles(string[] filenames, ProcessDatabase DoIt)
{
Document doc = acadApp.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
foreach (string filename in filenames)
{
if ((File.GetAttributes(filename) & FileAttributes.ReadOnly) == 0)
{
try
{
if (filename == doc.Name)
using (Database db = doc.Database)
{
DoIt.Invoke(db);
db.SaveAs(filename, DwgVersion.Current);
}
else
{
using (Database db = new Database(false, true))
{
db.ReadDwgFile(filename, FileShare.ReadWrite, true, string.Empty);
DoIt.Invoke(db);
db.SaveAs(filename, DwgVersion.Current);
}
}
}
catch (Autodesk.AutoCAD.Runtime.Exception aex)
{
if ((aex.ErrorStatus == ErrorStatus.FileSharingViolation) || (aex.ErrorStatus == ErrorStatus.FileAccessErr))
ed.WriteMessage("\n \"{0}\" is already opened", filename);
else if (aex.ErrorStatus == ErrorStatus.DwgNeedsRecovery)
ed.WriteMessage("\n\"{0}\" needs a recovery", filename);
else if (aex.ErrorStatus == ErrorStatus.BadDwgHeader)
ed.WriteMessage("\n\"{0}\" has a bad header", filename);
else
ed.WriteMessage("\n\"{0}\" AutoCAD error: {1}", filename, aex.Message);
}
catch (System.Exception ex)
{
ed.WriteMessage("\n\"{0}\" System error: {1}", filename, ex.Message);
}
}
else
ed.WriteMessage("\n\"{0}\" is read only", filename);
}
}
}
}
Using examples:
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Windows;
using BatchProcess;
namespace BatchCommands
{
public class Commands
{
[CommandMethod("TEST1")]
public void test1()
{
OpenFileDialog.OpenFileDialogFlags flag = OpenFileDialog.OpenFileDialogFlags.AllowMultiple;
OpenFileDialog ofd = new OpenFileDialog("Select files", "", "dwg", "", flag);
Process.ProcessDatabase DoIt = AddCircle;
if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
Process.ProcessFiles(ofd.GetFilenames(), DoIt);
}
}
private void AddCircle(Database db)
{
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
Circle c = new Circle(new Point3d(0.0, 0.0, 0.0), new Vector3d(0.0, 0.0, 1.0), 10.0);
btr.AppendEntity(c);
tr.AddNewlyCreatedDBObject(c, true);
tr.Commit();
}
}
[CommandMethod("TEST2")]
public void test2()
{
OpenFileDialog.OpenFileDialogFlags flag = OpenFileDialog.OpenFileDialogFlags.AllowMultiple;
OpenFileDialog ofd = new OpenFileDialog("Select files", "", "dwg", "", flag);
Process.ProcessDatabase DoIt = EraseCircle;
if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
Process.ProcessFiles(ofd.GetFilenames(), DoIt);
}
}
private void EraseCircle(Database db)
{
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
foreach (ObjectId id in btr)
{
Circle c = tr.GetObject(id, OpenMode.ForRead, false) as Circle;
if ((c != null) && (c.Center == new Point3d(0.0, 0.0, 0.0)) && (c.Radius == 10.0))
{
c.UpgradeOpen();
c.Erase();
}
}
tr.Commit();
}
}
}
}