Accessing DWG files not open in the AutoCAD editor using .NET

This topic was briefly introduced almost a year ago, in this post. I then looked into the code a little further in a follow-up post. But at the time this topic wasn't the main thrust of the post, it was really more of an implementation detail.

So now it's time to do the topic a little more justice. 🙂

Let's start with some terminology. What we're talking about today are often referred to as "side databases" or "external databases". Basically they're DWG files that are not open in the AutoCAD editor, but ones we want to access programmatically to load geometry or settings. You may also hear the term "lazy loaded" - these DWG files are not loaded completely into memory (unless you choose to access all the data stored in them), they are brought in, as needed, making the access very efficient.

Side databases have been available through ObjectARX since it was introduced in R13, but were introduced more recently in COM (the AxDb implementation was introduced several releases back, although I can't remember exactly when... perhaps it was in AutoCAD 2000 but it might have been later) and .NET (when we introduced the managed layer in 2005, I believe). One interesting point to note, is that any code you write using ObjectARX or .NET to access side databases can be used with almost no modification on top of RealDWG to access the same data outside AutoCAD. Although any code that's intermingled which accesses AutoCAD-resident functionality will not work, of course.

The basic technique is to create a Database object, and read a DWG file into it. Please remember to use the appropriate constructor: the standard constructor without arguments creates a Database object that cannot be used in this manner (it creates one that you would typically use to create a new DWG file). When reading a DWG you will need to pass False as the first argument - what you pass as the second depends on your need.

From there you work with the Database object, accessing the header variables and the objects stored in the various dictionaries and symbol tables, just as you would inside AutoCAD.

Let's take a very simple example, where we open a particular file on disk, and iterate through the model-space, listing a little bit of data about each object:

using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.DatabaseServices;

using Autodesk.AutoCAD.EditorInput;

using Autodesk.AutoCAD.Runtime;

namespace ExtractObjects

{

  public class Commands

  {

    [CommandMethod("EOF")]

    static public void ExtractObjectsFromFile()

    {

      Document doc =

        Application.DocumentManager.MdiActiveDocument;

      Editor ed = doc.Editor;

      // Ask the user to select a file

      PromptResult res =

        ed.GetString(

          "\nEnter the path of a DWG or DXF file: "

        );

      if (res.Status == PromptStatus.OK)

      {

        // Create a database and try to load the file

        Database db = new Database(false, true);

        using (db)

        {

          try

          {

            db.ReadDwgFile(

              res.StringResult,

              System.IO.FileShare.Read,

              false,

              ""

            );

          }

          catch (System.Exception)

          {

            ed.WriteMessage(

              "\nUnable to read drawing file."

            );

            return;

          }

          Transaction tr =

            db.TransactionManager.StartTransaction();

          using (tr)

          {

            // Open the blocktable, get the modelspace

            BlockTable bt =

              (BlockTable)tr.GetObject(

                db.BlockTableId,

                OpenMode.ForRead

              );

            BlockTableRecord btr =

              (BlockTableRecord)tr.GetObject(

                bt[BlockTableRecord.ModelSpace],

                OpenMode.ForRead

              );

            // Iterate through it, dumping objects

            foreach (ObjectId objId in btr)

            {

              Entity ent =

                (Entity)tr.GetObject(

                  objId,

                  OpenMode.ForRead

                );

              // Let's get rid of the standard namespace

              const string prefix =

                "Autodesk.AutoCAD.DatabaseServices.";

              string typeString =

                ent.GetType().ToString();

              if (typeString.Contains(prefix))

                typeString =

                  typeString.Substring(prefix.Length);

              ed.WriteMessage(

                "\nEntity " +

                ent.ObjectId.ToString() +

                " of type " +

                typeString +

                " found on layer " +

                ent.Layer +

                " with colour " +

                ent.Color.ToString()

              );

            }

          }

        }

      }

    }

  }

}

Here's what happens when you run the code:

Command: EOF

Enter the path of a DWG or DXF file: "C:\Program Files\Autodesk\AutoCAD

2007\Sample\Sheet Sets\Architectural\S-03.dwg"

Entity (2127693096) of type Line found on layer Struc_Plan_GB_PL with colour

BYLAYER

Entity (2127693104) of type Line found on layer Struc_Plan_GB_PL with colour

BYLAYER

Entity (2127693112) of type Line found on layer Struc_Plan_GB_PL with colour

BYLAYER

Entity (2127693120) of type Line found on layer Struc_Plan_GB_PL with colour

BYLAYER

Entity (2127693128) of type Line found on layer Struc_Plan_GB_PL with colour

BYLAYER

Entity (2127693224) of type Line found on layer Struc_Plan_GB_PL with colour

BYLAYER

Entity (2127693232) of type Line found on layer Struc_Plan_GB_PL with colour

BYLAYER

Entity (2127693368) of type Line found on layer Struc_Plan_Ext with colour

BYLAYER

Entity (2127693376) of type Line found on layer Struc_Plan_Ext with colour

BYLAYER

Entity (2127693384) of type Line found on layer Struc_Plan_Ext with colour

BYLAYER

Entity (2127693392) of type Line found on layer Struc_Plan_Ext with colour

BYLAYER

Entity (2127693400) of type Line found on layer Struc_Plan_Ext with colour

BYLAYER

Entity (2127693408) of type Line found on layer Struc_Plan_Ext with colour

BYLAYER

Entity (2127693416) of type Line found on layer Struc_Plan_Ext with colour

BYLAYER

Entity (2127693424) of type Line found on layer Struc_Plan_Ext with colour

BYLAYER

Entity (2127695000) of type Line found on layer 2_Arch_Plan_Dim with colour

BYLAYER

Entity (2127695448) of type BlockReference found on layer 0 with colour BYLAYER

Entity (2127624240) of type BlockReference found on layer Building Section (2)

with colour BYLAYER

Entity (2127656048) of type BlockReference found on layer Structrual Base2 with

colour BYLAYER

Entity (2127656304) of type BlockReference found on layer grid plan with colour

BYLAYER

Entity (2127656560) of type BlockReference found on layer Stair 2 with colour

BYLAYER

I'm interested in looking at more complex scenarios where people might need to access side databases from their code. Please post any suggestions you might have as a comment (or just drop me an email).

  1. Nikolay Poleshchuk Avatar
    Nikolay Poleshchuk

    Thank you Kean for the theme,
    One of the frequent problems is to check all (or some) dwg files in a folder. It is necessary to detect a valid dwg version, to check for some specific entities (present or absent), to add some objects (e.g. format box) and to publish (or to plot).

  2. Kean Walmsley Avatar

    Hi Nikolay,

    Thanks - this is great input.

    I'll try to cover the batch-processing aspect (going through files in a folder, checking their versions, and then reading/performing some operation), but printing/plotting can only happen on editor-resident drawings.

    AutoCAD currently needs the graphics pipeline to generate printed graphics, and this is not present for side databases. So this is certainly something interesting to cover, but would be more about batching inside the editor than using side databases.

    Regards,

    Kean

    1. hi kean this code is not working in objectarx , not getting entities without opening autocad

      1. Sorry - I don't know enough to say what's wrong. It certainly worked for me when I wrote it 9 years ago. I suggest posting the problematic code to the AutoCAD .NET forum.

        Kean

  3. Nick Schuckert Avatar
    Nick Schuckert

    Hi Kean!

    Excellent example! From an academic stand-point, what would really make this appliction "shine" is replacing the command line prompt with a Windows Form.

    Regards,

    Nick

  4. Hi Kean

    Great topic. I would be interested in opening drawing database and change attribute text in a blockrefrence. Save and close in the end.

    Cheers
    Tore

  5. Nikolay Poleshchuk Avatar
    Nikolay Poleshchuk

    Kean,
    If plotting is impossible in an invisible mode then let us save modified dwg file to a subfolder "Ready for plotting".

  6. Good example.But I want to know if I can access the entities in a drawing without start the AutoCAD.Maybe this is a DBX topic,but I know nothing about DBX,where I can find some helpful articles like here?You know I take here as my ObjectARX classroom:),Do you know some other blogs talk about ObjectDBX ?Thank you.

  7. Kean Walmsley Avatar

    Travor -

    I'm not sure if you're aware, but RealDWG is the new name for ObjectDBX (and I did mention RealDWG in the above article, albeit briefly).

    The above code will work with very little modification in RealDWG, and I'll add it to my list to do a specific article on RealDWG at some point.

    Regards,

    Kean

    1. Kean, thanks for the examples. I'm also interested in accessing the dwg file database outside of running a class/command inside of AutoCAD, as we had have many LT users. Is there a way to do this without purchasing RealDWG?
      Thanks,
      Ken

  8. Hi Kean.
    Thank you for your mention.It seems I should get something about RealDWG.I am looking forward to your RealDWG articles.Many thanks.

  9. Hi Kean,

    I've really enjoyed reading your articles. This is the best resource I have found for AutoCAD .NET programming. Thank you.

    I am working (or about to start) on creating a program that goes through the dwg files in a directory and purges each drawing. Don't ask why one would want to do this as it is not for me :), but it what I'm interested in and it kind of ties in with the first poster's desire to iterate through a list of drawings.

    Thanks again.

  10. Just read your latest post. It seems you have already done this. While here though, is it possible to do what I asked using the PurgeAll() command? (I haven't experimented yet, and I'm being lazy). Thanks again.

  11. Hi Kyle,

    You could fire off the -PURGE ALL command (sending the command to the commandline - this would mean the drawing had to be loaded in the AutoCAD editor, mind) or you could create a list of all the objects (blocks, layers, linetypes, etc.) and pass that list through to db.Purge(). This would remove any objects that should not be purged. The remaining object IDs in the list can be used to open and erase the purgable objects in the drawing.

    I'll add this to my list to tackle, at some point.

    Regards,

    Kean

  12. That's great information Kean. I am interested in how it can be accomplished through the C++ code/Arx. What about doing this with system variables such as dimtxt, dimscale etc?

    Here is my problem scenario. I have a block in drawing A1.dwg, and now I want to insert A1.dwg block into another drawing A2.dwg. I am trying to get the dimtxt value for A1.dwg before the insertion process so that I can perhaps set the current drawings dimtxt attribute to the one from A1.dwg. I know it's quite simple for current drawings, but what about other drawings remotely.

    So to sum it up, the function should be able to read dimtxt system variable from a drawing that is not open and return the dimtxt value for that drawing.

    Vector

  13. I think the possible solution to this problem would be to use ObjectDBX. However, as per my information there is no way to access system variables from another drawing that is not open in an AutoCAD session through ObjectDBX. Not even GetVariable and SetVariable, since GetVariable and SetVariable are methods of AcadDocument,
    they only work on AcadDocuments (they're just wrappers for the ObjectARX counterpart of the (getvar) and (setvar) LISP
    functions). So there's no method for getting/setting system variables stored in drawings that are accessed directly via
    ObjectDBX.

    Could you please confirm on this?

    Thanks,
    vector

  14. Vector -

    As long as you have a pointer to the Database (or AcDbDatabase) then you can access the "Dimtxt" property - db.Dimtxt (or use the AcDbDatabase::dimtxt() function).

    This is true whether inside AutoCAD or using RealDWG (the new name for ObjectDBX).

    Regards,

    Kean

  15. Kean:

    Do you know what signature would work? I can't find the Object Model documentation anywhere :

    Suppose I do this

    AcDbDatabase pDb( Adesk::kFalse );
    pDb.dimtxt(dimtxtVal, DwgName);

    is this the right signature?

    Where DwgName is the drawing name whose dimtxt I want

    Thanks,
    Vector

  16. Vector -

    You need to use readDwgFile() to read your DWG into the AcDbDatabase before accessing the dimTxt() method using:

    double dt = db.dimtxt();

    You'll find the documentation on the ObjectARX SDK under the docs folder.

    It seems as though you're new to using ObjectARX. Are you sure you want to stick with C++, rather than using .NET? (Even without substantial documentation I find AutoCAD .NET coding easier and the object model much more discoverable).

    A word of caution... I'd recommend against developing anything in ObjectARX (C++) unless you've worked through the Labs (in the "arxlabs" folder) or attended introductory training provided by my team. It will really save you a lot of thrashing.

    Regards,

    Kean

  17. Kean,

    How to access the ACADMap ObjectData Tables, without opening the dwg in ACAD Editor.

    Senthil

  18. Sorry, Senthil - I don't know the Map 3D APIs and am unlikely to address this topic on this blog.

    You should submit your question via one of the discussion groups or the ADN website (if you're a member).

    Kean

  19. hi kean
    this is satheesh from india.i'm currently assined wth an autocad automation project where i hv to draw in autocad from .net environment.i'm using managed dlls with c# as my programming language .
    i'm currently stuck in a sitaution where i hv to do fillet command to join two lines.for ur knowledge i 'm just a beginner who hv just started learning about autocad.net programming.u might feel this is a simple doubt,but it wud be a great help for me.
    thanx

  20. Satheesh -

    Please post your question to the AutoCAD .NET Discussion Group, or submit it via ADN, if you're a member.

    Regards,

    Kean

  21. hi
    please,
    Im after openning file dwg closed autocad .
    im guide please
    bye

  22. Kean Walmsley Avatar

    Sorry - I don't understand, but it doesn't seem related to the code in this post. Please submit your question to one of the discussion groups.

    Kean

  23. I get a eBadDwgHeader exception when trying to open dxf files. Is it possible to open dxf files with db.ReadDwgFile() or is there another way to open/import them using RealDWG?

  24. You can use RealDwgFile(). It's probably a problem with the DXF file, or with the Database constructor.

    Make sure you don't use the default constructor (Database db = new Database();).

    For R13-R2009 DWG files use:

    Database db = new Database(false, ...);

    For earlier DWGs use:

    Database db = new Database(true, ...);

    Kean

  25. I have tried different Database constructors but DXF files still give eBadDwgHeader exceptions, even with your EOF example. DWG files works fine.

    I'm using RealDWG 2009 and have added
    acdbmgd.dll and acmgd.dll to the projects references. All my dxf files can be opened correctly in autocad.

    Regards,

    Mattias

  26. Hi Matthias,

    At this stage, I have to refer you to ADN support, I'm afraid.

    Hopefully you're already a member, but otherwise you might consider joining (RealDWG development is hard to do without assistance).

    Regards,

    Kean

  27. Hi Kean,

    I have found a solution to my problem. 🙂

    It seems that db.DxfIn() does the trick once you use the correct Database constructor as you described in you other reply.

    Regards,

    Mattias

  28. Hi Kean,
    I am upgrading projects from ADT2006 to AA2008 and since areas become spaces now, I have created a new property data set to be used with the new (and old areas converted) spaces. Now, how can I copy data entered on the previous (areas) property data set into the corresponding fields of the new spaces property data set? Say, if we have assigned fields for area codes, area names, scheduled areas in the areas property data set - how do I copy these into the corresponding fields of the new spaces property data set? Any suggestions would be much appreciated. The idea is to use the new spaces property data set and purge the areas one. Is there a way of accessing the dwg database directly and then using a VB routine to do this copy-paste business? Thanks, JP

  29. Hi JP,

    Sorry - this is really not my area of expertise.

    I suggest submitting your question via the ADN website (if you're a member) or otherwise trying the AutoCAD Architecture Customization Discussion Group.

    Regards,

    Kean

  30. I am curious how i would go about using a selection set in an external file. I can read blocks all that information perfectly fine. I have an SQL database where i store the part handle of a closed polyline. I then use that geometry location as a selection set. Any help?

  31. SelectionSets are very much an AutoCAD concept (not one that is inside RealDWG, for instance). Selection happens via AutoCAD's knowledge of entities' graphics: when DWGs are not open in the editor you cannot select across them, other than by iterating across the contents and checking their geometric representation.

    Although I may very well have misunderstood your question...

    Kean

  32. Kean,
    For Autocad 2009, is it still required for files to be open in editor mode for printing & plotting?

    Thanks.

  33. Mike,

    Yes, it is.

    Kean

  34. Hi Kean
    I am trying to open a dwg file without editor and without realdwg but with autocad running so
    AcadApp = GetObject(, "AutoCAD.Application.16.2")

    My program stop at line
    Dim DBDwg As New Autodesk.AutoCAD.DatabaseServices.Database for "Access violation exception"
    Can you help my?
    oohh...i am using VB.net
    thank

  35. Stefano,

    You seem to mixing both COM and .NET in your project... not that that's a bad thing, necessarily, but there's a lot I can't tell from the code you've provided.

    I don't have time to provide personal debugging services, so please post more information on what you're trying to do via the ADN website (if you're a member) or to the AutoCAD .NET Discussion Group (if you're not).

    Regards,

    Kean

  36. how to create a group which has 3 polyline

  37. Asmaa - perhaps someone on the discussion group can help you. I unfortunately don't have the time to handle this type of request.

    Kean

  38. merci j'ai trouvé la solution :

    // creer un group

    Transaction tm = db.TransactionManager.StartTransaction();
    ObjectId[] ids = new ObjectId[3];
    ids[0] = pol.ObjectId;
    ids[1] = fin_barre_droit.ObjectId;
    ids[2] = fin_barre_gauche.ObjectId;
    Group gp = new Group("grouptest", true);
    DBDictionary dict = (DBDictionary)tm.GetObject(db.GroupDictionaryId, OpenMode.ForWrite, true);
    dict.SetAt("group", gp);
    for (int i = 0; i < 3; i++) gp.Append(ids[i]);
    tm.AddNewlyCreatedDBObject(gp, true);
    tm.Commit();

  39. merci j'ai trouvé la solution :

    // creer un group

    Transaction tm = db.TransactionManager.StartTransaction();
    ObjectId[] ids = new ObjectId[3];
    ids[0] = pol1.ObjectId;
    ids[1] = pol2.ObjectId;
    ids[2] = pol3.ObjectId;
    Group gp = new Group("grouptest", true);
    DBDictionary dict = (DBDictionary)tm.GetObject(db.GroupDictionaryId, OpenMode.ForWrite, true);
    dict.SetAt("group", gp);
    for (int i = 0; i < 3; i++) gp.Append(ids[i]);
    tm.AddNewlyCreatedDBObject(gp, true);
    tm.Commit();
    db.Dispose();

  40. I want to read a DWG file, make a graphical representation(2d) on screen, and sort individual objects in the drawing to list it on the screen separately.
    Eg: if the drawing is of a floor plan of a room, i want to display the floor plan, and list the furniture shown in the drawing.

    Is this possible using realDWG?
    or is there any other api/sdk which can be used?
    Do you have any article which will be of help to me to get started with the scenario above?
    Any other links which will be of help to me?

  41. If you're going to display your own symbolic graphical representation which is different from the way AutoCAD (for instance) would show it, then RealDWG might work.

    RealDWG doesn't have any entity display capabilities, so if you want anything to look like AutoCAD it's going to be a lot of work... at that point I'd recommend taking a look at AutoCAD OEM.

    Kean

  42. Hi Kean

    Really very useful information and I liked the article very much.
    I have to read .dwg file [ this dwg is from another application which have custom entities ] and I have to read this .dwg file. Is this possible through Object DBX.
    Can ObjectDBX read the custom entities information from the .dwg file.
    Could you please provide your valuable advice regarding this.

    Many thanks in Advance and please note that this information is very important to me , so I request you to kindly share your view on the same.

    Once again thanks in Advance

    Hillary

  43. Hi Hillary,

    RealDWG - what was previously known as ObjectDBX - can read custom objects and custom entities if the object enabler is well structured (i.e. it has no dependencies on AutoCAD) and is installed on the system. Otherwise it will only have access to information exposed by the proxy objects created for them.

    Regards,

    Kean

  44. Hi Kean

    Many Many thanks for your reply and information.
    But Could you please provide more information regarding the statmement "if the object enabler is well structured (i.e. it has no dependencies on AutoCAD)"

    The drawing I am going to read is made of many custom entities like complex line and circle which are derived from AcDbEntity Custom entities.Could you please your valuable advice whether we can read all this information successfully through ObjectDBX.

    Best Regards
    Hillary

  45. Yes, you should be able to access your custom entity information from RealDWG.

    Ultimately the issue is about the DLLs you link to from your Object Enabler via import libraries. If you use the Dependency Walker to check the dependencies, if AutoCAD (acad.exe) is there in any way, it will not load in RealDWG.

    The best way to check this without a RealDWG license is probably to install DWG TrueView on a fresh computer and make sure it loads the Object Enabler (you should be able to tell via the graphics, or failing that you can use tools such as ProcessMonitor from Microsoft/SysInternals) when AutoCAD is not present.

    Kean

  46. Hi Kean

    Once again many thanks for your time and advice.
    The drawings created by third party application is shipped with .arx executable [ no .dbx executables are shipped].

    Could you please provide your valuable advice regarding whether reading the custom entities from .dwg file through ObjectDBX is possible with out .dbx executables from third party application.

    Also, if the third party application has to ship .dbx application [which currently ships only .arx executables ] will this going to be big work for them .

    Once again Many many thanks
    Best Regards
    Hillary

  47. You'll need .dbx modules without dependencies on AutoCAD-only EXEs/DLLs. Without these it won't work.

    How much effort would it take? It depends on the application - it can be very straightforward, but there might be reasons it's complicated, in this case. I have no way to judge that.

    Kean

  48. Hi Kean, i'm developing my personal application on c# 2008. with autocad 2006. i want to edit a dwg file without opening autocad is there a way for it? currently i can open autocad, insert blocks, line, etc on the drawing, plot to a jpeg file and close autocad from my app, but i would like to do the same without having to load the complete program.are there libraries to do this? dlls? hope you can help me or at least guide me... thanks a lot!

  49. Kean Walmsley Avatar

    Hi Francisco,

    If you have AutoCAD installed on the system then I believe it's possible to use the AutoCAD/ObjectDBX Common Type Library to work with documents, although without AutoCAD running you will not be able to plot to a JPEG - you need AutoCAD's graphics pipeline for that.

    The same is true for working on systems without AutoCAD installed: you could use RealDWG to access/modify DWGs, but plotting will be an issue.

    Regards,

    Kean

  50. Now that I see how to look at these objects without opening the drawing in the editor, I was wondering if it were possible to do the following:
    Loop through all text objects
    If the text object's value = "SomeString"
    text Object's value = "DifferentString"
    Next

    I have a TON of drawings I need to be able to do this on!
    Thank You!
    -Brian

  51. Brian -

    Yes, that's altogether possible.

    In the iteration code you can cast the object to a DBText or MText to retieve and check it's text contents. There should be cold elsewhere on this blog that does just that (try searching the site for "DBText MText").

    Regards,

    Kean

  52. I think I'm close. My code runs without error and exits properly, but when I open the drawing I've processed, nothing has changed 🙁 I don't know if I'm supposed to post code here, but I figured I'd try!

    namespace TEST2
    {
    public class Class1
    {
    // Changes text in a file without opening it
    [CommandMethod("ctext")]
    static public void changeText()
    {
    Document doc = Application.DocumentManager.MdiActiveDocument;
    Editor ed = doc.Editor;

    // Create a database and try to load the file
    Database db = new Database(false, true);

    using (db)
    {
    try
    {
    //Ask for the file name to process; hard coded for now...
    //PromptResult fileName = ed.GetString("\nEnter the file path of a Dwg to process: ");
    string fileName = "C:\\Documents and Settings\\bwiggins\\Desktop\\BL-NUT.dwg";

    //Open the file to edit
    db.ReadDwgFile(fileName, System.IO.FileShare.ReadWrite, false, "");
    }
    catch (System.Exception)
    {
    ed.WriteMessage("\nUnable to read drawing file.");
    return;
    }

    //Get what text to replace & what to replace it with
    PromptResult oldText = ed.GetString("\nEnter the text you want to replace: ");
    PromptResult newText = ed.GetString("\nEnter the text you want to replace " + '"' + oldText.StringResult + '"' + " with: ");

    if (oldText.Status == PromptStatus.OK & newText.Status == PromptStatus.OK)
    {
    //Start the transaction...
    Transaction myTrans = db.TransactionManager.StartTransaction();
    using (myTrans)
    {
    // Open the blocktable, get the modelspace
    BlockTable bt = (BlockTable)myTrans.GetObject(db.BlockTableId, OpenMode.ForWrite);
    BlockTableRecord btr = (BlockTableRecord)myTrans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);

    // Iterate through all text objects
    foreach (ObjectId objId in btr)
    {
    DBObject obj = myTrans.GetObject(objId, OpenMode.ForWrite);

    if (obj is DBText)
    {
    //Cast the object as a text object
    DBText textObj = (DBText)obj;

    //Test if it matches the oldText
    if (textObj.TextString == oldText.StringResult)
    {
    textObj.TextString = newText.StringResult;
    }
    }
    }
    myTrans.Commit();
    }
    }
    }
    }
    }
    }

    Thanks again for your help!!!
    -Brian

  53. Hi Kean,
    Sorry if you think this is a stupid question.
    Should I download/buy RealDWG to run those code or just autocad ?

  54. Hi Ferry,

    That's up to you: you can run this code in AutoCAD as it stands, or modify it slightly to work inside a RealDWG application.

    It comes down to what you have available already (i.e. whether you already own AutoCAD) and how you want to deploy the application (i.e. whether you're going to run this as a batch process on your machine or deploy it to a number of other machines which won't have AutoCAD available).

    Kean

  55. Hi Brian,

    It looks like you need to save the document using db.Save() or db.SaveAs().

    Kean

  56. Kean,
    I just wanted to thank you again! I added the db.SaveAs(fileName,DwgVersion) command to the end and it works great! I had some trouble figuring out that 'DwgVersion.AC1800' correlates with AutoCAD's 2004 version. I kept trying 'DwgVersion.AC1018', since 'AC1018' is in the drawing file when you send one saved in the 2004 format to a text editor. Is there a list somewhere that shows what each 'DwgVersion.XXXX' correlates with?

    Thanks again in advance!
    -Brian Wiggins

  57. Brian,

    This old post includes a partial list (not covering AutoCAD 2010), but it should be enough for you.

    Kean

  58. Kean,
    That's the post I was looking at to get 'AC1018 = 2004/2005/2006' ; which is incorrect in code (at least on my PC). I'm using AC2008 and references to AcDbMgd and AcMgd from ObjectARX 2008.
    From my code:
    db.SaveAs(db.Filename, DwgVersion.AC1018) = ERROR!!!
    db.SaveAs(db.Filename, DwgVersion.AC1800) = Saved correctly in 2004/2005/2006

    Please let me know if it's just me?!?!
    Thank You,
    -Brian

  59. That is strange...

    When I save DWGs for different versions and check the first 6 bytes of each, I see:

    2004-2006 AC1018
    2007-2009 AC1021
    2010 AC1024

    I had assumed the DwgVersion enumeration followed these, but apparently not (there's no DwgVersion.AC1018, from what I can tell).

    I'll check and see if anyone knows what's up with this.

    Kean

  60. I assumed the same thing; how odd that it's not consistent! I'm glad it's not just me though 🙂

  61. No - not just you... 🙂

    Looking at the ObjectARX headers (acdb.h), the codes appear to come from there:

    ...
    kDHL_1001 = 8,
    kDHL_1002 = 9, // AutoCAD 2.5
    kDHL_1003 = 10, // AutoCAD 2.6
    kDHL_1004 = 11, // Release 9
    kDHL_1005 = 12,
    kDHL_1006 = 13, // Release 10
    kDHL_1007 = 14,
    kDHL_1008 = 15,
    kDHL_1009 = 16, // R11 and R12
    kDHL_1010 = 17,
    kDHL_1011 = 18,
    kDHL_1012 = 19, // R13
    kDHL_1013 = 20, // R14 mid version.
    kDHL_1014 = 21, // R14 final version.
    kDHL_1500 = 22, // 2000 development (Tahoe)
    kDHL_1015 = 23, // 2000 final version.
    kDHL_1800a = 24, // 2004 mid version
    kDHL_1800 = 25, // 2004 final
    kDHL_2100a = 26, // 2007 Development
    kDHL_1021 = 27, // 2007 final
    kDHL_2400a = 28, // Gator Development
    kDHL_1024 = 29, // 2010 final
    kDHL_Newest = kDHL_1024,
    kDHL_CURRENT = kDHL_Newest,
    ...

    Whatever the reason for doing so, the enumeration names are now as they are. It looks to me as though the "in development" DWG version for AutoCAD 2004 was not renamed properly at the end of the development cycle.

    Anyway - we are where we are, at this stage...

    Kean

  62. Kean,

    At least now you have a topic for a new (although short) post 🙂

    Since I'm making a post anyway...
    When I do this:
    btr = (BlockTableRecord)myTrans.GetObject(bt[BlockTableRecord.PaperSpace], OpenMode.ForWrite);
    It only operates on the default layout. How do I loop through and process ALL the layouts in a drawing?

    Thanks,
    -Brian

  63. Brian,

    If you search this blog for "btrId" and look for code that uses "foreach" to loop through the contents of the BlockTable, you should find a few posts (such as this one).

    Kean

  64. Kean,
    I would like to know how to generate a preview picture of a DWG file on the fly and display it in a Windows form. I have found many posts that offer components to bring up a thumbnail, but this image is too small. I need a preview that is approximately 375 pixels wide. Users of my software will need to see the labels in the drawing clearly, so thumbnails will not offer enough detail. How can I do this?
    Thank You,
    Kaitlyn

  65. Kaitlyn,

    Your comment doesn't appear to relate to this post. In future, please submit your questions to the ADN team, if you're a member, or otherwise the AutoCAD .NET Discussion Group.

    That said, you might find these posts to be of interest:

    Taking a snapshot of the AutoCAD model (take 2)
    November’s Plugin of the Month: Screenshot

    Regards,

    Kean

  66. Neyton Luiz Dalle Molle Avatar
    Neyton Luiz Dalle Molle

    Hello Kean, this very interesting post!

    Even now I am using your idea!

    But I have a problem, you can determine the coordinates of the region modelspace that a viewport is rectangular, using the database of an open design with ReadDwgFile?

    (google translate... sorry, heheh)

  67. Hello Neyton Luiz Dalle Molle,

    I'm afraid I don't understand what you're looking for. In any case, I'm afraid it will go beyond the scope of this post (and I don't have time to provide support, myself).

    Please submit your question to the ADN team, if you're a member, or otherwise the AutoCAD .NET Discussion Group.

    Kean

  68. Hey Kean. Can you help me with something ? I want to show the image stored in a .dwg file to a picture box. I am currently working in C# visual studio 2008.

  69. Hi Usman,

    There's a DWG Thumbnail control that's available via ADN, and I believe there are alternatives out there, too (although I don't really know anything about them).

    Kean

  70. Okay. Thanks for your early reply.

  71. Hi Kean,
    Thanks for all the help you provide in your posts. Is there a way to access a "side database" that contains custom objects? Is there a way to reference the custom dbx through .NET?

  72. Hi Restov,

    Absolutely: as long as you have the registry entries set up (under [HKCU|HKLM]\Software\Autodesk\ObjectDBX\Rxx.x\Applications) then the .dbx modules should be loaded by any RealDWG/ObjectDBX host on the system (when a custom object of that type is found).

    Regards,

    Kean

  73. Hi Kean, thanks for this code! I have been searching high and low for something like it. Here is my situation...

    I need to import dwg models into 3DS Max. I can do this. 🙂 Each dwg object that get's imported is linked to a SQL database ala Autocad Plant 3D. I need to either:

    a)pull the dwg objects UID from the database and make the UID it's name in Max
    or
    b)read each dwg object property as you have done and find the UID property of the object and make that the object name in Max. . I am not sure if the property I am looking for is stored in the dwg but it would be great if it was. In thinking about it I guess it would have to be for the Autocad to pull the data. Maybe it's not exposed to the user tho?

    Basically, I just need an object property that I can use to query the database. I figured naming the object with the UID was the easiest thing to do.

    I am exhausted just writing this and will not be offended if you don't answer. 😛

  74. Kean Walmsley Avatar

    The classic way to link DWG objects with outside databases is via their "handle" property: these are guaranteed to be unique for a particular drawing (and do not change from session to session).

    Kean

  75. Kean, what references do I need to load to execute this program? All I have available is "using Autodesk.AutoCAD.Interop"

    Sorry for the newb question.

  76. Kean Walmsley Avatar

    Dave,

    You will need project references (with Copy Local set to False) to AcMgd.dll and AcDbMgd.dll (this post may help).

    Regards,

    Kean

  77. Hi Kean,
    I would to know if RealDWG allows us reading/writing dwg layers extended properties (I mean... layer extended data).

    Thanks for your time.

    Regards,
    Adriano

  78. Hi Adriano,

    I'm pretty sure it does, although I haven't tried it (at least not that I remember).

    Regards,

    Kean

  79. I have created C#.Net Class Library and not want to see output .but i m not able to see it.
    So could you tell me how can i get the out .

  80. I'm sorry - firstly I don't really understand what you're asking, and secondly I don't have time to provide support. Please post your question to the ADN team or to the AutoCAD .NET Discussion Group.

    Kean

  81. Kean,

    Thank you for the article because it provided a great solution for creating a list of products specified in dwgs without opening them. I am trying to take it a step further by providing a simple editor to correct the MText contents without opening the drawing. The concept is to find the MText object, set the contents equal to the new value and commit the change without opening the dwg. I am not getting any errors but the contents are not updated. Can I do what I am trying to do? If yes, have you written on it?

    Regards,

    Ken

  82. Ken,

    A couple of thoughts: the above code is not currently set up to write data to a file. You'll need to commit the transaction - for a start - and then use the Database.SaveAs() method to write it back to disk.

    Regards,

    Kean

  83. Thanks Kean -

    It's good to know that I will be able to do this. Originally I didn't call the SaveAs() method in my code but after adding it and working past the 'eFileSharingViolation' I was still not able to update the file. I will post my code to the Discussion Group to see if I can get it resolved.

    Again, thanks for your help!

    Ken

  84. Hello Kean,
    This is a nice example that I would like to use as a basis for a function in my app. I've got it working and slimmed it down just to get the db.ThumbnailBitmap.

    However, there is a warning in the ObjectARX SDK Managed Class Reference in the Database.ReadDwgFile method that's a bit scary - quote:

    "This function should only be used on a newly created Database that was created with its constructor's buildDefaultDrawing argument set to false. If this method is used on an Database that was created with buildDefaultDrawing set to true, or an Database that already has information in it (for any reason including a previous call to this function), then memory leaks, or worse, will result."

    What's the likelihood I'll hit the problems mentioned?

  85. Hi Craig,

    If going to use ReadDwgFile(), you should really pass in false as the first argument to the Database constructor (as I've done here). That means everything gets read in from the DWG. You use true if you're not going to read anything in (or if you're reading in an R12 DWG, which is pretty rare, these days).

    Cheers,

    Kean

  86. I should have read the code more closely. ASslong as the database is newly created I'll be okay. Phew 😉
    Database db = new Database(false, true);

  87. Need to AutoCad for this?

  88. I got error following error.

    Method 'CopyTo' in type 'Autodesk.AutoCAD.ApplicationServices.DocumentCollection' from assembly 'acmgd, Version=18.1.0.0, Culture=neutral, PublicKeyToken=null' does not have an implementation.

    Please Clarify my doubts. Thanks in advance.

  89. Kean Walmsley Avatar

    Yes, you need AutoCAD for this (otherwise you'd use RealDWG, but the code would be slightly different).

    Make sure you include a project reference to AcCoreMgd.dll if using AutoCAD 2013 or later, by the way.

    Kean

  90. Thanks for your reply. I will check.

  91. Hi Kean,

    I've got this code up and running. I'm fairly new to VB.NET and am wondering if the code could be extended to look deeper into things like attribute values? Using the BlockTableId etc. there is no .Has Attributes or the like. Not looking for sample code, just wondering if it is possible and perhaps what command I should be investigating? Thanks

  92. Kean Walmsley Avatar

    Hi Peter,

    Yes, that's a pretty common use case. If you search the blog for AttributeDefinition and/or AttributeReference, you should find some posts that help.

    Regards,

    Kean

  93. Thanks. Its a pleasure to learn.

  94. Kean, thank you for posting this. I am just getting started in .net and was hoping to access some dwg data without having to open the drawing. I have Acad 2014 installed > ObjARX 2014 dll's to a folder > create a new Console application in VS 2010.

    I have removed your code about asking for the drawing name and have hard coded the drawing name here:

    db.ReadDwgFile(
    "c:/mydwg.dwg", //also tried @"c:\mydwg.dwg"
    System.IO.FileShare.Read,
    false,
    ""
    );

    I get the OK from the console that it sees the file.

    It falls over at:

    Transaction tr =
    db.TransactionManager.StartTransaction();

    err: InvalidProgramException

    with the error marker underneath the start transaction () parens.

    Have I provided enough information for you to know what is going on?

    Thank you!

  95. Are you running this from the main AutoCAD program folder?

    I tend not to even try this approach - as I don't believe it's supported and may just fail in odd ways - so I'd suggest doing what's in this post, which is to have AutoCAD running but able to work on drawings that are not loaded in the editor.

    If you want a true standalone experience then there's always RealDWG, but then I understand you may not want to use it if you have AutoCAD installed.

    If you're using AutoCAD 2013 or higher then you really ought to check out the Core Console. That's IMO the best way to go here.

    Kean

  96. Is is possible to read or use more than 1 dwg file into 1 editor? I have created a palette which displays dwg files and i wanted to do a drag and drop of the selected dwg i am displaying on a listview. I was successful with 1 dwg but dragging the 2nd dwg cause the 1st dwg to be lost.

  97. It definitely is. It depends how you're doing it, of course (you need to take care about document locking, etc.).

    I suggest posting some code to ADN or the AutoCAD .NET Discussion Group.

    Kean

  98. Hi Kean,

    I need to acess raster images source in the dwg and replace for a new one. Do you think it's possible without having to open the drawing?

    I tried your code just to test acess the dwg but i'm getting "InvalidProgramException" error in line:

    Document doc = Application.DocumentManager.MdiActiveDocument;

    Any suggestion? I'm using AutoCAD MAP 3D 2013, Visual Studio 2012 and ObjectARX 2014.

    Thank you!

  99. Hi David,

    It should be fairly simple to test: raster images are external files, so you could try modifying the external file without the DWG being open and then check the effect when you reload the drawing.

    Regards,

    Kean

  100. Hi Kean,
    I try to access a drawing file and plot its model space without opening it in the editor.
    I read database by using ReadDwgFile and it is working fine until this step.
    However, there is an error with message "eLayoutNotCurrent"
    when I validate plot information.
    piv.Validate(pi); - at this line
    Does it happen because I didn't open layout in editor
    Is there any alternative way I can try?

    Thank you

  101. Hi Paul,

    You won't be able to plot from a drawing that isn't loaded in the editor: plotting is dependent on the graphics subsystem.

    But you should be able to use the Core Console to plot, however (whether via the standard command or a .NET DLL).

    Regards,

    Kean

  102. Ken,

    You might want to take a look at AutoCAD I/O.

    keanw.com/2014/10/autocad-io-api-a-new-batch-processing-web-service.html

    (Also check developer.autodesk.com.)

    Regards,

    Kean

  103. Kean,
    In my model space there are different blocks and each block has several attributes. I want to read particular attribute.
    So after opening modelspace block table record how to iterate through all blocks and in each block how to iterate through all attributes?

    Please help.

    Thanks,
    Pankaj

  104. Pankaj,

    Does this help?

    keanw.com/2006/09/getting_autocad.html

    Regards,

    Kean

  105. Hello Kean,
    I went through this link before, but here you select block and then iterate through attribute.
    Whats the way to iterate though all blocks in drawing?
    and for iterating through all blocks do I need to go though all block table records or I need to just go though model space block table record?
    Sorry if question is novice!!

    Thanks for help
    Pankaj

    1. Hi Pankaj,

      For block definitions...

      You can use foreach to list all the ObjectIds of blocks in the BlockTable, and then open the block (check for IsLayout and !IsAnonymous, depending on your needs).

      For block references, you iterate the contents of the modelspace.

      Regards,

      Kean

      1. thanks Kean, that was very helpful.

        I could achieve reading attributes.

        However with bunch of stuff on drawing it gives error that "Unable to cast object of type

        autodesk.autocad.databaseservices.polyline to type autodesk.autocad.databaseservices.blockrefereance.

        Code:

        Dim db As Database = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Database

        Using tr As Transaction = db.TransactionManager.StartTransaction

        Dim ed As Editor = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor

        Dim blockids As ObjectIdCollection = New ObjectIdCollection

        Dim bt As BlockTable = tr.GetObject(db.BlockTableId, OpenMode.ForRead)

        Dim btr As BlockTableRecord = tr.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForRead)

        For Each objid As ObjectId In btr

        If btr.IsAnonymous = False Or btr.IsLayout = False Then

        Dim blkref As BlockReference = tr.GetObject(objid, OpenMode.ForRead)

        Dim attcol As AttributeCollection = blkref.AttributeCollection

        For Each attid As ObjectId In attcol

        Dim attref As AttributeReference = tr.GetObject(attid, OpenMode.ForRead)

        ed.WriteMessage(attref.Tag.ToString & vbNewLine)

        ed.WriteMessage(attref.TextString.ToString & vbNewLine)

        Next

        End If

        Next

        tr.Commit()

        End Using

        Can you please help!!!

        1. Sorry, Pankaj - I really don't have time to provide support. Please post these questions to the AutoCAD .NET Discussion Group.

          forums.autodesk.com/

          Kean

          1. Anyways thanks Kean, for all your valuable suggestions , I am huge fan of you!
            Let me know If you are anytime visiting to Columbia, I will be glad to meet you.

  106. Hello Kean,

    Is it possible to write to dwg file without opening them?
    Like I want o place blocks on dwg file from some other dwg file without opening it?

    Thanks,
    Pankaj

  107. Hi Pankaj,

    Yes - search my blog for "side database" or "ReadDwgFile".

    For instance:
    keanw.com/2007/07/accessing-dwg-f.html
    keanw.com/2006/08/import_blocks_f.html

    Regards,

    Kean

  108. Hello Kean,

    thanks for reply...I went through both blogs, they talk about reading dwg file without opening it and importing blocks from file which is not open.

    But I was really interested in is writing to blank dwg file which is not open.

    Sorry for poor English

    thanks,
    Pankaj

    1. Hello Pankaj,

      You can create a blank Database by passing the right arguments to the constructor (this is well documented).

      Please do use the discussion forum for these questions.

      Regards,

      Kean

  109. Kean, I need to open a series of drawings and bind xreferences then close them. Any ideas? All my other requests seem to go unanswered, but here is hoping, just this one time.

    1. Brett, if you'd checked my blog you'd have seen I've just been on vacation for 2 weeks. I always respond to comments, even if it's just to say that I don't have time to provide support.

      I suggest taking a look at what commands are needed to do this (probably -_XREF _BIND) and then using ScriptPro 2.0 to perform a script against a set of drawings.

      Kean

  110. Pankaj Potdar Avatar

    Hello Kean,

    I there way to use Readdwgfile command on file which is open?
    Like create side database from file which is open?
    Thanks,
    Pankaj

    1. Kean Walmsley Avatar

      Hi Pankaj,

      You could probably copy the DWG and read it in. I can't think of a strong reason to do this, though.

      Regards,

      Kean

      1. Pankaj Potdar Avatar

        One of the situation is, I have template drawing on server and there are like thousands of users in different country different time zones, who are using readdwgfile command in their application to create their side databases from this template.
        If some one open main template to update it, users get error.

        1. Kean Walmsley Avatar

          That sounds like a reason not to do it. I'd suggest having a central copy the application accesses as read-only via ReadDwgFile, and some system that copies the updated (original) version of the file onto the copy when it edited manually. In any case having everyone accessing the same central file in this way sounds very risky.

          Kean

          1. Pankaj Potdar Avatar

            Thanks Kean, really valuable suggestion. I would lean toward making local copy from central template and use it to create side database.
            Thanks once again
            Pankaj

  111. Kean. I too would like .Net examples of accessing a dwg file's database outside of running a class/command inside of an instance of AutoCAD AND without ACCoreConsole AND without purchasing RealDWG. I thought leveraging HostApplicationServices.WorkingDatabase would do the trick, but I was mistaken; unless I am missing something.

    1. Kean Walmsley Avatar

      Search the blog (and the web) for ReadDwgFile() - that should give you some samples that show how to do this. Assuming you want to access a drawing not opened in the editor, that is (what's known as a "side database").

      Kean

  112. Anyone knows how to read .dim (AutoCAD dimension style) file in c#?

    1. Kean Walmsley Avatar

      Hi Kapil,

      Please post support questions to the AutoCAD .NET forum.

      Thanks,

      Kean

  113. Christopher Beech Avatar
    Christopher Beech

    Hi, I work for a company that has a document management system (M-Files) database that runs on firebird SQL. I want to be able to update the titleblock attribute data of an autoCAD dwg using project data from within the firebird SQL database. The user may not have autoCAD installed to be able to run scripts froom within AutoCAD, so is there a way to achieve this without autoCAD? Any help would be greatly appreciated.

    1. Kean Walmsley Avatar
      Kean Walmsley

      Hi Christopher,

      You could look at either using RealDWG (a toolkit for editing DWG files) or the Design Automation API in Forge. Both of these will work, it just depends on whether you want a local install or to use the cloud.

      Best,

      Kean

      1. Christopher Beech Avatar
        Christopher Beech

        Would there be a way through using the M-Files api? RealDWG is pretty expensive for us.

        1. Kean Walmsley Avatar
          Kean Walmsley

          Possibly. I don't know anything about M-Files.

          Kean

  114. Hi keen, thanks a lot for this example. my issue is to add entities to an existing dwg file in the disk an save changes without accessing to it. thank you.

    1. I suggest posting to the AutoCAD .NET forum - someone there will be able to help.

      Kean

  115. When I using ReadDwgFile method to read an DWG file, The method throw an Exception say:"eNotImplementYet",Why?

    1. Please post some code to the AutoCAD .NET forum: someone there will be able to help.

      Kean

  116. Hi Kean,
    I have a question.
    I tried to do test to getpoint(location of Entity('ent')), but I couldn't get the result of location(point3D).
    Do you have an idea?
    I need your help.
    Thanks,

    1. Hello,

      Please post your support questions to the AutoCAD .NET forum: someone there will be able to help.

      Best,

      Kean

  117. Siddharam Padamgond Avatar
    Siddharam Padamgond

    Hi,
    I am trying to replace text by other text in autocad using c#.net can you please provide the idea.

    1. Please post to the discussion groups.

      Kean

  118. بَحرانی اِحسان Avatar
    بَحرانی اِحسان

    hey Kean
    i'm sorry for replying this after years.

    is it possible to read dwg file and locate dynamic blocks without opening autocad application?! (it has been installed but i want to do it with a separated application without showing autocad)

    after that, is it possible to save file based on that dynamic blocks? (copy multiple of dynamic blocks with specific properties for each one)

    thanks and sorry again

    1. You can either use RealDWG (which requires licensing separately) or launch AutoCAD and keep it invisible, loading the plugins you need, driven by some kind of script.

      I really don't have time to provide support, so please post follow-up questions to the relevant online support forum.

      Kean

Leave a Reply to Hillary Cancel reply

Your email address will not be published. Required fields are marked *