📐 AutoCAD APIintermediateautomation

Batch Process AutoCAD Drawings with .NET API

Automate processing of multiple AutoCAD drawings using the .NET API for bulk operations and standardization.

0 views12/14/2025

Batch Process Multiple AutoCAD Drawings

Application: AutoCAD .NET API
Category: Automation
Difficulty: Intermediate
Language: C#

Problem

You need to process multiple DWG files automatically - for example, updating block attributes, purging unused objects, or exporting data - without manually opening each file.

Solution

Use AutoCAD's Database class to open drawings in the background without displaying them in the UI. This approach is much faster than opening files through the UI and allows true batch processing.

Code Example

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using System;
using System.IO;

[CommandMethod("BATCHPROCESS")]
public void BatchProcessDrawings()
{
    Document doc = Application.DocumentManager.MdiActiveDocument;
    Editor ed = doc.Editor;
    
    // Get folder containing drawings
    string folderPath = @"C:\Drawings\ToProcess";
    
    if (!Directory.Exists(folderPath))
    {
        ed.WriteMessage("\nFolder not found!");
        return;
    }
    
    // Get all DWG files
    string[] dwgFiles = Directory.GetFiles(folderPath, "*.dwg");
    
    ed.WriteMessage($"\nFound {dwgFiles.Length} drawings to process");
    
    int successCount = 0;
    int errorCount = 0;
    
    foreach (string dwgPath in dwgFiles)
    {
        try
        {
            ed.WriteMessage($"\nProcessing: {Path.GetFileName(dwgPath)}");
            
            // Open drawing in background (not in UI)
            using (Database db = new Database(false, true))
            {
                db.ReadDwgFile(dwgPath, FileOpenMode.OpenForReadAndAllShare, false, "");
                
                using (Transaction tr = db.TransactionManager.StartTransaction())
                {
                    // Process the drawing
                    ProcessDrawing(db, tr);
                    
                    tr.Commit();
                }
                
                // Save changes
                db.SaveAs(dwgPath, DwgVersion.Current);
            }
            
            successCount++;
        }
        catch (Exception ex)
        {
            ed.WriteMessage($"\nError processing {Path.GetFileName(dwgPath)}: {ex.Message}");
            errorCount++;
        }
    }
    
    ed.WriteMessage($"\n\nBatch processing complete!");
    ed.WriteMessage($"\nSuccessful: {successCount}");
    ed.WriteMessage($"\nErrors: {errorCount}");
}

private void ProcessDrawing(Database db, Transaction tr)
{
    // Example: Count and report block references
    BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
    BlockTableRecord modelSpace = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord;
    
    int blockCount = 0;
    
    foreach (ObjectId objId in modelSpace)
    {
        Entity ent = tr.GetObject(objId, OpenMode.ForRead) as Entity;
        if (ent is BlockReference)
        {
            blockCount++;
        }
    }
    
    // You can add any processing logic here:
    // - Update block attributes
    // - Purge unused layers
    // - Export data to Excel
    // - Modify text styles
    // - etc.
}

Advanced: Export Data from Multiple Drawings

using System.Collections.Generic;
using System.Text;

public class DrawingData
{
    public string FileName { get; set; }
    public int LayerCount { get; set; }
    public int BlockCount { get; set; }
    public int TextCount { get; set; }
}

[CommandMethod("EXTRACTDATA")]
public void ExtractDataFromDrawings()
{
    Document doc = Application.DocumentManager.MdiActiveDocument;
    Editor ed = doc.Editor;
    
    string folderPath = @"C:\Drawings\ToAnalyze";
    string[] dwgFiles = Directory.GetFiles(folderPath, "*.dwg");
    
    List<DrawingData> dataList = new List<DrawingData>();
    
    foreach (string dwgPath in dwgFiles)
    {
        try
        {
            using (Database db = new Database(false, true))
            {
                db.ReadDwgFile(dwgPath, FileOpenMode.OpenForReadAndAllShare, false, "");
                
                using (Transaction tr = db.TransactionManager.StartTransaction())
                {
                    DrawingData data = new DrawingData
                    {
                        FileName = Path.GetFileName(dwgPath)
                    };
                    
                    // Count layers
                    LayerTable lt = tr.GetObject(db.LayerTableId, OpenMode.ForRead) as LayerTable;
                    data.LayerCount = lt.Count;
                    
                    // Count blocks and text
                    BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
                    BlockTableRecord modelSpace = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord;
                    
                    foreach (ObjectId objId in modelSpace)
                    {
                        Entity ent = tr.GetObject(objId, OpenMode.ForRead) as Entity;
                        if (ent is BlockReference) data.BlockCount++;
                        if (ent is DBText || ent is MText) data.TextCount++;
                    }
                    
                    dataList.Add(data);
                    tr.Commit();
                }
            }
        }
        catch (Exception ex)
        {
            ed.WriteMessage($"\nError: {ex.Message}");
        }
    }
    
    // Export to CSV
    StringBuilder csv = new StringBuilder();
    csv.AppendLine("File Name,Layers,Blocks,Text Objects");
    
    foreach (var data in dataList)
    {
        csv.AppendLine($"{data.FileName},{data.LayerCount},{data.BlockCount},{data.TextCount}");
    }
    
    string csvPath = Path.Combine(folderPath, "DrawingAnalysis.csv");
    File.WriteAllText(csvPath, csv.ToString());
    
    ed.WriteMessage($"\nData exported to: {csvPath}");
}

Key Points

  • Use Database.ReadDwgFile() to open drawings without UI
  • Always use using statements to ensure proper disposal
  • FileOpenMode.OpenForReadAndAllShare allows opening files that are open in other applications
  • Call SaveAs() to save changes back to the file
  • Batch processing is much faster than opening files through the UI

Performance Tips

  • Process drawings in order of file size (smallest first) for faster feedback
  • Consider parallel processing for large batches (use caution with file I/O)
  • Use Database.CloseInput(true) to release file handles immediately
  • Disable undo recording for faster processing: db.UndoRecording = false

Common Pitfalls

Mistake: Not disposing the database properly

// WRONG - memory leak
Database db = new Database(false, true);
db.ReadDwgFile(path, FileOpenMode.OpenForReadAndAllShare, false, "");
// Database never disposed!

// CORRECT
using (Database db = new Database(false, true))
{
    db.ReadDwgFile(path, FileOpenMode.OpenForReadAndAllShare, false, "");
    // Automatically disposed
}

Mistake: Opening files with wrong file mode

// WRONG - fails if file is open elsewhere
db.ReadDwgFile(path, FileOpenMode.OpenForReadAndWriteNoShare, false, "");

// CORRECT - allows shared access
db.ReadDwgFile(path, FileOpenMode.OpenForReadAndAllShare, false, "");

Related Topics

  • Database class fundamentals
  • Transaction management
  • File I/O operations
  • Script automation
  • ObjectARX batch processing

Code Example

C#
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using System;
using System.IO;

[CommandMethod("BATCHPROCESS")]
public void BatchProcessDrawings()
{
    Document doc = Application.DocumentManager.MdiActiveDocument;
    Editor ed = doc.Editor;
    
    // Get folder containing drawings
    string folderPath = @"C:\Drawings\ToProcess";
    
    if (!Directory.Exists(folderPath))
    {
        ed.WriteMessage("\nFolder not found!");
        return;
    }
    
    // Get all DWG files
    string[] dwgFiles = Directory.GetFiles(folderPath, "*.dwg");
    
    ed.WriteMessage($"\nFound {dwgFiles.Length} drawings to process");
    
    int successCount = 0;
    int errorCount = 0;
    
    foreach (string dwgPath in dwgFiles)
    {
        try
        {
            ed.WriteMessage($"\nProcessing: {Path.GetFileName(dwgPath)}");
            
            // Open drawing in background (not in UI)
            using (Database db = new Database(false, true))
            {
                db.ReadDwgFile(dwgPath, FileOpenMode.OpenForReadAndAllShare, false, "");
                
                using (Transaction tr = db.TransactionManager.StartTransaction())
                {
                    // Process the drawing
                    ProcessDrawing(db, tr);
                    
                    tr.Commit();
                }
                
                // Save changes
                db.SaveAs(dwgPath, DwgVersion.Current);
            }
            
            successCount++;
        }
        catch (Exception ex)
        {
            ed.WriteMessage($"\nError processing {Path.GetFileName(dwgPath)}: {ex.Message}");
            errorCount++;
        }
    }
    
    ed.WriteMessage($"\n\nBatch processing complete!");
    ed.WriteMessage($"\nSuccessful: {successCount}");
    ed.WriteMessage($"\nErrors: {errorCount}");
}

private void ProcessDrawing(Database db, Transaction tr)
{
    // Example: Count and report block references
    BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
    BlockTableRecord modelSpace = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord;
    
    int blockCount = 0;
    
    foreach (ObjectId objId in modelSpace)
    {
        Entity ent = tr.GetObject(objId, OpenMode.ForRead) as Entity;
        if (ent is BlockReference)
        {
            blockCount++;
        }
    }
    
    // You can add any processing logic here:
    // - Update block attributes
    // - Purge unused layers
    // - Export data to Excel
    // - Modify text styles
    // - etc.
}