.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Dynamic XREFs

1 REPLY 1
SOLVED
Reply
Message 1 of 2
cpmcgrat
766 Views, 1 Reply

Dynamic XREFs

Hey all,

 

So I've been building an application that creates 6 files and dynamically xrefs them all to each other (i.e. test1.dwg will xref to test2.dwg test3.dwg test4.dwg test5.dwg and test6.dwg then test2 will xref test1, test3 etc....).

 

When I manually open one of the created files and run the command to do the xreffing it has no issue. However when I open the file from the application and try to create the xrefs dynamically it throws me an eFileAccessError.

 

I have tried letting the system sleep when it opens and moving the path for the files into AutoCAD's root directory, but the error still gets thrown. Does anyone have any idea why this would be happening?

 

___________________________________________________________________________________________________

 

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.EditorInput;
using System.Windows.Forms;
using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

public class Commands
{

    /// <summary>
    /// Builds a file, draws on hardcoded lines then saves that file six times
    /// </summary>
    [CommandMethod("BuildSixXref", CommandFlags.Session)]
    public static void BuildDrawSave()
    {

        Document acDoc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;

 

        string basepath = "C:\\Autodesk\\Autodesk-test";

        if (basepath.EndsWith("\\")) { }
        else
        {
            basepath = basepath + "\\";
        }

 

        string basename = "test";

 

        // Loop 6 times to create 6 new files
        for (int i = 1; i <= 6; i++)
        {
            //Dynamically generate filepath and name
            string filename = basename + i.ToString();
            string fullpath = basepath + filename;

            SaveDrawing(fullpath);
        }

 

        acDoc.CloseAndDiscard();

 

        DocumentCollection acDocMgr = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager;

 

        // Loop 6 times decrementally to build the 6 xrefs
        for (int i = 6; i >= 1; i--)
        {

            string filename = basename + i.ToString();
            string fullpath = basepath + filename;

            acDocMgr.Open(fullpath, false);

            System.Threading.Thread.Sleep(1000);

            BuildXref(fullpath);

            acDoc.CloseAndSave(fullpath);

        }
    }

    /// <summary>
    /// Builds the xrefs between files
    /// </summary>
    public static void BuildXref(string path)
    {
        Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
        HostApplicationServices hs = HostApplicationServices.Current;

 

        // Split the path found into chunks
        string[] splitpath = path.Split(System.IO.Path.DirectorySeparatorChar);
        string basepath = "";
        string filename = GetFileName(path);

        // Isolate filename and add the other chunks back together
        for (int i = 0; i < (splitpath.Length - 1); i++)
        {
            basepath += splitpath[i] + "\\";
        }

 

        //Finds all the files in the directory of the current file
        string[] files = Directory.GetFiles(basepath);

 

        //Sets up new list to hold the files which should be xreffed
        List<string> xrefs = new List<string>();

 

        //Parse through the files array and skip over any files containing the filename
        //Since those will not be xreffed
        foreach (string file in files)
        {
            if (file.Contains(filename)) { }
            else
            {
                //Check if the file contains the basename specified when the files were built
                //If not an xref to that file is not built
                if (file.Contains(filename.Remove(filename.Length - 1)) && Path.GetExtension(file) == ".dwg")
                {
                    //Adds file to the list "xrefs" for use by a transaction later
                    xrefs.Add(file);
                    doc.Editor.WriteMessage("\nFile: " + file);
                }
            }
        }

 

        //Build xrefs in currently opened file
        //Get the current database and open transaction
        Database acCurDb = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Database;

        foreach (string xref in xrefs)
        {
            string overlayName = GetFileName(xref);
            ObjectId xrefId = acCurDb.OverlayXref(xref, overlayName);

 

            using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
            {
                BlockTable bt = acCurDb.BlockTableId.GetObject(OpenMode.ForRead) as BlockTable;
                BlockTableRecord ms = bt[BlockTableRecord.ModelSpace].GetObject(OpenMode.ForWrite) as BlockTableRecord;
                BlockReference bref = new BlockReference(Point3d.Origin, xrefId);
                ms.AppendEntity(bref);
                acTrans.AddNewlyCreatedDBObject(bref, true);
                acTrans.Commit();
            }
        }
    }

 

    /// <summary>
    /// Takes a path and returns the filename without extension
    /// </summary>
    /// <param name="path"></param>
    /// <returns></returns>
    public static string GetFileName(string path)
    {
        return path.Split(System.IO.Path.DirectorySeparatorChar).Last().Split(new char[] { '.' })[0];
    }

 

    /// <summary>
    /// Saves the current file being worked on
    /// </summary>
    /// <param name="fullpath">Contains the full path to where a file should be saved to</param>
    public static void SaveDrawing(string fullpath)
    {
        Document acDoc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
        acDoc.Database.SaveAs(fullpath, true, DwgVersion.Current, acDoc.Database.SecurityParameters);
    }

}

 

1 REPLY 1
Message 2 of 2
khoa.ho
in reply to: cpmcgrat

I've tried your code and got the same error "eFileAccessError". However, your code does not look optimized for readable and performance. Then I came with my solution based on your requirements.

 

[CommandMethod("BuildDynamicXrefs")]
public static void BuildDynamicXrefs()
{
    Document doc = Application.DocumentManager.MdiActiveDocument;
    string basePath = "C:\\Temp\\Test";
    string baseName = "Temp";
    int count = 6;
    List<string> filePaths = new List<string>();

    // Loop to create new files
    for (int i = 1; i <= count; i++)
    {
        // Dynamically generate file paths and names
        string fileName = baseName + i.ToString() + ".dwg";
        string filePath = Path.Combine(basePath, fileName);
        Database db = new Database();
        db.SaveAs(filePath, DwgVersion.Current);
        db.Dispose();
        filePaths.Add(filePath);
    }

    // Xref all other drawings to the selected drawing
    for (int i = 0; i < count; i++)
    {
        string filePath = filePaths[i];
        using (Database db = new Database())
        {
            db.ReadDwgFile(filePath, System.IO.FileShare.ReadWrite, false, null);
            using (Transaction trans = db.TransactionManager.StartTransaction())
            {
                var blockTable = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead);
                var modelSpace = (BlockTableRecord)trans.GetObject(
                    blockTable[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
                foreach (string xrefPath in filePaths)
                {
                    // Skip the current drawing out of xref list
                    if (xrefPath != filePath)
                    {
                        // Overlay (or Attach) xref to drawing
                        ObjectId xrefObjId = db.OverlayXref(xrefPath,
                            Path.GetFileNameWithoutExtension(xrefPath));
                        // Create a new block reference to hold the added xref
                        var blockRef = new BlockReference(Point3d.Origin, xrefObjId);
                        // Add new xref entity to model space
                        modelSpace.AppendEntity(blockRef);
                        modelSpace.DowngradeOpen();
                        // Update transaction for new added entity
                        trans.AddNewlyCreatedDBObject(blockRef, true);
                    }
                }
                trans.Commit();
            }
            db.SaveAs(filePath, DwgVersion.Current); // Save xrefs list back to the drawing
            db.CloseInput(true); // Close file
        }
    }
}

 

The code will create 6 drawings (Temp1.dwg to Temp6.dwg). Then for each drawing, xref all other drawings (except itself). I use db.ReadDwgFile which will work at backend without opening drawing in AutoCAD editor. Therefore, the performance is faster and get rid of all visible activities in AutoCAD.

 

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report

”Boost