Author Topic: Open, Bind and Close  (Read 11007 times)

0 Members and 1 Guest are viewing this topic.

mcarson

  • Guest
Open, Bind and Close
« on: August 19, 2008, 09:44:00 AM »
Some of our guys have made the mistake of binding the xrefs into the current drawing and saving; overwriting the current file. It has been asked if it is possible to create a command that binds all the loaded xrefs into the current drawing, saving as a different file.
That's not really the problem. The guys are needing the original drawing (unbound) kept open/reopened in the editor after closing the bound version!

I am using VS2005, .NET 2.0 and AutoCAD 2008.

Code to bind all xrefs into the current drawing: (converted from VB)

Code: [Select]
public static bool BindAllXRefs()
{
    //Get the active document
    Autodesk.AutoCAD.ApplicationServices.Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
    //Get the active database
    Database db = doc.Database;
    //Get the xref graph
    XrefGraph xrefg = db.GetHostDwgXrefGraph(true);
    //Check if the xref graph is empty or contains just the current drawing
    if (xrefg.IsEmpty || xrefg.NumNodes == 1) {
        return false;
        return; // TODO: might not be correct. Was : Exit Function
    }
   
    //Start a new transaction to get the exreferences
    using (Transaction tr = doc.TransactionManager.StartTransaction) {
        //Get the current block table
        BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
       
        //Loop through all the xrefs in the block table
        for (int i = 1; i <= xrefg.NumNodes - 1; i++) {
            //Get the graph node
            XrefGraphNode xrefn = (XrefGraphNode)xrefg.GetXrefNode(i);
            //Only bind loaded xrefs
           
            if (!(xrefn.XrefStatus == XrefStatus.Unloaded)) {
                //Get the blocktable record
                BlockTableRecord btr = (BlockTableRecord)tr.GetObject(xrefn.BlockTableRecordId, OpenMode.ForWrite, false);
                //Get any inserted xrefs
                ObjectIdCollection BlkRefCollection = btr.GetBlockReferenceIds(true, true);
                //If the block exists then add and bind
                if (BlkRefCollection.Count > 0) {
                    ObjectIdCollection ObjIdCollection = new ObjectIdCollection();
                    //Add the object id to the collection
                    ObjIdCollection.Add(btr.Id);
                    //Do the bind
                    db.BindXrefs(ObjIdCollection, true);
                }
                else {
                    //Detach the xrefs if not loaded
                    db.DetachXref(btr.Id);
                }
            }
        }
        tr.Commit();
        return true;
    }
}

I tried the following 'horrible' workaround attempt; the idea of which was to work on a temporary copy of the drawing:

Code: [Select]
public static bool BindDrawing(string OpenFileName, string SaveFileName)
{
    //Open the database transparently
    string tempname = "C:\\temp.dwg";
    System.IO.File.Copy(OpenFileName, tempname);
    using (Database db = new Database(false, true)) {
        //Read in the drawing file
        db.ReadDwgFile(tempname, System.IO.FileShare.Read, true, null);
        //Set the current working database
        if (db != HostApplicationServices.WorkingDatabase) {
            HostApplicationServices.WorkingDatabase = db;
        }
        //Get the xref graph
        XrefGraph xrefg = db.GetHostDwgXrefGraph(true);
        //Check if the xref graph is empty (contains just the current drawing)
        if (xrefg.IsEmpty || xrefg.NumNodes == 1) {
            //We don't need to bind, so discard the database
            db.Dispose();
            return true;
            return; // TODO: might not be correct. Was : Exit Function
        }
        //Drawing has ex-references
        //Start a new transaction
        using (Transaction tr = db.TransactionManager.StartTransaction) {
            //Get the block table of the database
            BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead, false);
            //Loop through the records in the block table to get all the xrefs
            for (int i = 1; i <= xrefg.NumNodes - 1; i++) {
                //Get the graph node
                XrefGraphNode xrefn = (XrefGraphNode)xrefg.GetXrefNode(i);
                //Only bind the loaded xrefs
                if (!(xrefn.XrefStatus == XrefStatus.Unloaded)) {
                    //Get the block table record that matches the xref node reference
                    BlockTableRecord btr = (BlockTableRecord)tr.GetObject(xrefn.BlockTableRecordId, OpenMode.ForWrite, false);
                    ObjectIdCollection BlkRefCollection = btr.GetBlockReferenceIds(true, true);
                    //If the xref exists as a block table record then add and bind
                    if (BlkRefCollection.Count > 0) {
                        ObjectIdCollection ObjIDCollection = new ObjectIdCollection();
                        //Add the object id to the collection
                        ObjIDCollection.Add(btr.Id);
                        //Do the bind
                        db.BindXrefs(ObjIDCollection, true);
                    }
                    else {
                        //Detach the xref if not loaded
                        db.DetachXref(btr.Id);
                    }
                }
            }
            tr.Commit();
        }
        db.RetainOriginalThumbnailBitmap = true;
        db.SaveAs(SaveFileName, DwgVersion.Current);
        db.CloseInput(true);
       
    }
    HostApplicationServices.WorkingDatabase = AppServices.DocumentManager.MdiActiveDocument.Database;
}
Some of the code used in the second method came from this site (Thanks Draftek).

This does not work as expected, in fact it doesn't bind in some cases!

Glenn R

  • Water Moccasin
  • Posts: 1932
  • What idiot child of married cousins wrote this?!
Re: Open, Bind and Close
« Reply #1 on: August 19, 2008, 09:52:26 AM »
It's probably not binding when it strikes a nested xref.

The way I would try to do this off the top of my head is:

1. Issue command in drawing to bind.
2. Save the current drawing or prompt user to save drawing before running command.
3. Create a new dbase and use ReadDwgFile to read the current drawing into the new dbase.
4. Do Bind Mojo
5. Probably use COM SaveAs to save in-memory dbase to another file.
6. Destroy temp dbase.
Me

mcarson

  • Guest
Re: Open, Bind and Close
« Reply #2 on: August 19, 2008, 11:01:02 AM »
I think I understand.
The drawing I am using for test purposes contains no nested xrefs and binds perfectly with the first method. I am able to do a save as, but I cannot CloseAndDiscard() 'Drawing is busy'
The second method doesn't allow me to bind. No errors, just strange behavior! Only difference is using the in-memory database.
If I was to readDwgFile the current open file, wouldn't I get a file lock error?

Maybe this:
Save the current drawing.
Issue the Bind Command.
Save the bound drawing as 'whatever'
Open the original drawing
Close the bound drawing.

I cannot seem to get my head around this. Do I have to start the command in the ApplicationContext? If so, how do I make sure I don't hit a zero-document interface.

Glenn R

  • Water Moccasin
  • Posts: 1932
  • What idiot child of married cousins wrote this?!
Re: Open, Bind and Close
« Reply #3 on: August 19, 2008, 11:33:01 AM »
Drawing A is open in the editor and has xrefs you want to bind.

1. Issue your command and bail if not saved.
2. Assuming drawing is saved, readdwg the file corresponding to drawing A into memory.
3. Issue a ResolveXrefs call on this new dbase.
4. Bind away.
5. SaveAs
6. Destroy.

I don't see a need for this to be ApplicationContext. Also, you will not hit a zero document state as drawing A is still open in the editor.
Me

mcarson

  • Guest
Re: Open, Bind and Close
« Reply #4 on: August 19, 2008, 04:05:33 PM »
Thanks for clarifying
Success - in part

I coded the following method (quickly)
Code: [Select]
public void BindXReferences()
{
    //Get the current document
    AppServices.Document doc = AppServices.Application.DocumentManager.MdiActiveDocument;
    //Get the active document's database
    Database db = doc.Database;
    //Save the drawing
    //db.Save()
    //Load a copy of the database into memory
    Database newdb = new Database(true, true);
    newdb.ReadDwgFile(doc.Name, IO.FileShare.ReadWrite, false, null);
    //resolve the xrefs in the newly created database
    newdb.ResolveXrefs(false, false);
    //now bind the xrefs
    //get the xref graph
    XrefGraph xrefg = newdb.GetHostDwgXrefGraph(true);
    //check if the xref graph contains more than just the current drawing
    if (xrefg.IsEmpty || xrefg.NumNodes == 1) {
        newdb.Dispose();
        return; // TODO: might not be correct. Was : Exit Sub
    }
   
    //Start a new transaction to get the exreferences
    using (Transaction tr = newdb.TransactionManager.StartTransaction) {
        //Get the current block table
        BlockTable bt = (BlockTable)tr.GetObject(newdb.BlockTableId, OpenMode.ForRead);
        for (int i = 1; i <= xrefg.NumNodes - 1; i++) {
           
            //Loop through all the xrefs in the block table
            //Get the graph node
            XrefGraphNode xrefn = (XrefGraphNode)xrefg.GetXrefNode(i);
            //Only bind loaded xrefs
           
            if (!(xrefn.XrefStatus == XrefStatus.Unloaded)) {
                //Get the blocktable record
                BlockTableRecord btr = (BlockTableRecord)tr.GetObject(xrefn.BlockTableRecordId, OpenMode.ForWrite, false);
                //Get any inserted xrefs
                ObjectIdCollection BlkRefCollection = btr.GetBlockReferenceIds(true, true);
                //If the block exists then add and bind
                if (BlkRefCollection.Count > 0) {
                    ObjectIdCollection ObjIdCollection = new ObjectIdCollection();
                    //Add the object id to the collection
                    ObjIdCollection.Add(btr.Id);
                    //Do the bind
                    newdb.BindXrefs(ObjIdCollection, true);
                }
                else {
                    //Detach the xrefs if not loaded
                    newdb.DetachXref(btr.Id);
                }
            }
        }
        tr.Commit();
    }
    //Save the database
    newdb.SaveAs("C:\\Documents and Settings\\Mark\\Desktop\\test\\final.dwg", DwgVersion.Current);
    //Destroy it
    newdb.Dispose();
}

Am I missing something? The bind doesn't work!

Glenn R

  • Water Moccasin
  • Posts: 1932
  • What idiot child of married cousins wrote this?!
Re: Open, Bind and Close
« Reply #5 on: August 19, 2008, 04:16:09 PM »
It's not binding because the ObjectIdCollection that 'BindXrefs' expects, is id's of BlockTableRecords, NOT, BlockReferenceIds.
Me

mcarson

  • Guest
Re: Open, Bind and Close
« Reply #6 on: August 19, 2008, 04:20:10 PM »
 :oops: Thanks for the correction - I think?
Wrote the following SimpleBind to demonstrate what's happening...

Code: [Select]
public void SimpleBind()
{
    //Load a copy of the database into memory
    Database newdb = new Database(true, true);
    newdb.ReadDwgFile("C:\\Documents and Settings\\Mark\\Desktop\\test\\main.dwg", IO.FileShare.ReadWrite, false, null);
    //resolve the xrefs in the newly created database
    newdb.ResolveXrefs(false, false);
    //now bind the xrefs
    //get the xref graph
    XrefGraph xrefg = newdb.GetHostDwgXrefGraph(true);
    //check if the xref graph contains more than just the current drawing
    if (xrefg.IsEmpty || xrefg.NumNodes == 1) {
        newdb.Dispose();
        return; // TODO: might not be correct. Was : Exit Sub
    }
   
    //Start a new transaction to get the exreferences
    using (Transaction tr = newdb.TransactionManager.StartTransaction) {
        //Loop through all the xrefs in the block table
        for (int i = 1; i <= xrefg.NumNodes - 1; i++) {
            //Get the graph node
            XrefGraphNode xrefn = (XrefGraphNode)xrefg.GetXrefNode(i);
            //Create a new object id collection for the block table record
            ObjectIdCollection ObjIdCollection = new ObjectIdCollection();
            //Add the blocktablerecord id to the collection
            ObjIdCollection.Add(xrefn.BlockTableRecordId);
            //Do the bind
            newdb.BindXrefs(ObjIdCollection, true);
        }
        tr.Commit();
    }
    //Save the database
    newdb.SaveAs("C:\\Documents and Settings\\Mark\\Desktop\\test\\final.dwg", DwgVersion.Current);
    //Destroy it
    newdb.Dispose();
}

Please note the lines:
            //Add the blocktablerecord id to the collection
            ObjIdCollection.Add(xrefn.BlockTableRecordId);
            //Do the bind
            newdb.BindXrefs(ObjIdCollection, true);
The bind does not work?!
I have checked the locals while debugging and everyting seems okay... maybe I'm tired - 9:45PM here
« Last Edit: August 19, 2008, 04:46:47 PM by mcarson »

Glenn R

  • Water Moccasin
  • Posts: 1932
  • What idiot child of married cousins wrote this?!
Re: Open, Bind and Close
« Reply #7 on: August 19, 2008, 05:06:06 PM »
I'm not a mind reader mate - why doesn't it work.
Also, you should be looping thru the XrefGraphNodes, adding the id's of BlockTableRecords you're interested in to your collection, then AFTER your loop, calling the bind exactly once - it doesn't make sense to be doing on each iteration of your loop.

As an aside, are you new to programming and .NET and ObjectARX in general?
Me

Glenn R

  • Water Moccasin
  • Posts: 1932
  • What idiot child of married cousins wrote this?!
Re: Open, Bind and Close
« Reply #8 on: August 19, 2008, 05:27:10 PM »
Also, it slipped my mind to ask: Have you done a search on this forum for all things relating to Binding?
Me

mcarson

  • Guest
Re: Open, Bind and Close
« Reply #9 on: August 19, 2008, 05:31:58 PM »
I did a few searches before posting - I did mention Draftek as a source for some of my code... maybe I should have replied to those.

Bit of my background...
AutoCAD Technician (AEC & Mechanical) about 13 years too long
Bit of a programmer, started with VBA in Office and then with a lot of AutoCAD VBA.
Employed as a CAD Manager type guy now (260 users!) and trying to create creating a standard for everyone.
Studying for my MCSD.
The AutoCAD API is fairly new to me. I have a lot to learn.

I don't want to leech; just learn by example.

Why?

« Last Edit: August 19, 2008, 05:35:46 PM by mcarson »

Glenn R

  • Water Moccasin
  • Posts: 1932
  • What idiot child of married cousins wrote this?!
Re: Open, Bind and Close
« Reply #10 on: August 19, 2008, 05:47:55 PM »
I was curious because of some of the code. The code from Draftek is actually from me originally I believe, vultured by somebody else. But that's neither here nor there.

As far as learning by example, that's fine - I can understand it. However, having said that, you're trying to go from VBA to VB.NET (if I remember correctly), which is a rather large jump. You have to contend with .NET in it's largesse and then the ObjectARX .NET API - not an easy task.

I'm just south of you (London), so we can converse tomorrow, however, I will leave you with this to navel gaze over.

Cheers,
Glenn.
Me

mcarson

  • Guest
Re: Open, Bind and Close
« Reply #11 on: August 20, 2008, 05:33:42 AM »
Yeah, I would agree that the AutoCAD API is quite a learning curve. Due to the 'limitations' of VBA in AutoCAD, I decided to move into .NET

Thanks for the link. A few queries though...

Used the code posted by you, but removed the dll import and added BindXRefs(). Worked perfectly.
The next stage was to find out if a bind could be carried out on an in-memory database.
The modified method quit out when resolving the xrefs.

Glenn R

  • Water Moccasin
  • Posts: 1932
  • What idiot child of married cousins wrote this?!
Re: Open, Bind and Close
« Reply #12 on: August 20, 2008, 06:06:22 AM »
Post your current code as something I can drop into a project and run ie a CommandMethod

260 users...by yourself!? That's steep.
Me

Glenn R

  • Water Moccasin
  • Posts: 1932
  • What idiot child of married cousins wrote this?!
Re: Open, Bind and Close
« Reply #13 on: August 20, 2008, 06:18:39 AM »
Hmmm....after looking through reflector at the '08 dll's it looks like BindXrefs calls the underlying ObjectARX function 'acdbBindXrefs'.

It's first argument is a pointer to the host dbase to do the bind operation on. Now, seeing the signature for BindXrefs doesn't ask what dbase to bind to, it's either assuming the current dbase or whatever HostApplicationServices.WorkingDatabase is set to.

You may have to do what I did in that other thread and use acedXrefBind and pass the last argument which is the dbase to bind to....
Me

Glenn R

  • Water Moccasin
  • Posts: 1932
  • What idiot child of married cousins wrote this?!
Re: Open, Bind and Close
« Reply #14 on: August 20, 2008, 06:21:38 AM »
Actually, it is assuming the current dbase as it's a method of Database :)
Me

mcarson

  • Guest
Re: Open, Bind and Close
« Reply #15 on: August 20, 2008, 06:31:15 AM »
Made another change: commented out the block that checks for resolved xrefs, and it worked. :?

Code: [Select]
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using AppServices = Autodesk.AutoCAD.ApplicationServices;

public class clsBindSupport : Autodesk.AutoCAD.Runtime.IExtensionApplication
{
   
   
    public void Autodesk.AutoCAD.Runtime.IExtensionApplication.Initialize()
    {
    }
   
    public void Autodesk.AutoCAD.Runtime.IExtensionApplication.Terminate()
    {
    }
   
    public clsBindSupport()
    {
        //Does nothing...
    }
   
    [CommandMethod("exBind")]
    public static void ExBind()
    {
        //Get the currently active document
        AppServices.Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
        //Get the document's database
        Database db = doc.Database;
        //Get the editor
        Editor ed = doc.Editor;
        //Get the path to the document
        string dwgprefix = Autodesk.AutoCAD.ApplicationServices.Application.GetSystemVariable("DWGPREFIX").ToString;
        //Get the name of the document
        string dwgname = Autodesk.AutoCAD.ApplicationServices.Application.GetSystemVariable("DWGNAME").ToString;
        //Strip the file extension from the document name
        string dwgtitle = Strings.Mid(dwgname, 1, Strings.Len(dwgname) - 4);
        //Create the new file name
        string newdwgfile = dwgprefix + dwgtitle + "_bound" + ".dwg";
       
        //Create a new database, reading the current drawing
        Database newdb = new Database(false, true);
        newdb.ReadDwgFile(doc.Name, IO.FileShare.ReadWrite, true, null);
       
        //Get the xref graph
        XrefGraph xrefGraph = newdb.GetHostDwgXrefGraph(true);
        //Check for xrefs
        if (xrefGraph == null || xrefGraph.IsEmpty || xrefGraph.NumNodes == 1) {
            ed.WriteMessage("" + Strings.Chr(10) + "No xrefs found.");
            newdb.Dispose();
            return;
        }
       
        //Problem occurred in the following If block. Couldn't resolve xrefs in the in-memory database
        //Comment it out to demonstrate the method working
       
        //TODO: Resolve xrefs on the original database before new database is created??
       
        //Check for unresolved xrefs
        if (xrefGraph.MarkUnresolvedTrees()) {
            ed.WriteMessage("" + Strings.Chr(10) + "Error: There are unresolved xrefs - bind aborted!");
            newdb.Dispose();
            return;
        }
       
       
       
       
        for (int i = 0; i <= xrefGraph.NumNodes - 1; i++) {
            XrefGraphNode xrefGraphNode = xrefGraph.GetXrefNode(i);
            if (xrefGraphNode == null) {
                ed.WriteMessage("" + Strings.Chr(10) + "Error: Failed to get a node on the graph - aborting!");
                newdb.Dispose();
                return;
            }
           
            // Is it the root node, which is the current drawing?
            // If it IS, then the number of incoming nodes will be 0...
            if (xrefGraphNode == xrefGraph.HostDrawing) {
                continue;
            }
           
            // Continue if it's truly nested as we can only bind "true" top level parents...
            if (xrefGraphNode.IsNested) {
                continue;
            }
           
            if (xrefGraphNode.NumIn == 1) {
               
                string xrefName = null;
                ObjectId xrefid;
               
                using (Transaction tr = newdb.TransactionManager.StartTransaction()) {
                   
                    BlockTableRecord btr = tr.GetObject(xrefGraphNode.BlockTableRecordId, OpenMode.ForRead, false) as BlockTableRecord;
                    if (btr == null) {
                        ed.WriteMessage("" + Strings.Chr(10) + "Error: Failed to get xref name - aborting!");
                        newdb.Dispose();
                        return;
                    }
                   
                    xrefName = btr.Name;
                    xrefid = btr.ObjectId;
                }
               
                if (xrefName != null) {
                   
                    ed.WriteMessage("" + Strings.Chr(10) + "Binding xref {0}...", xrefName);
                   
                    //acedXrefBind(xrefName, False, False, IntPtr.Zero)
                    ObjectIdCollection ids = new ObjectIdCollection();
                    ids.Add(xrefid);
                    newdb.BindXrefs(ids, true);
                   
                }
               
            }
        }
        //Copy the preview bitmap from the original database
        newdb.RetainOriginalThumbnailBitmap = true;
        //Save the new drawing file
        newdb.SaveAs(newdwgfile, DwgVersion.Current);
        //Destroy the database, as we no longer need it
        newdb.Dispose();
    }
}

Read the comments in the code - may work, just need to make the changes.

260 users; the good thing at the moment is that only 10% know I exist.
the bad thing is that after I deploy AutoCAD 2008, the other 90% will...
With CAD standards (wrong forum, sorry) the hardest thing is getting everyone to change.

Glenn R

  • Water Moccasin
  • Posts: 1932
  • What idiot child of married cousins wrote this?!
Re: Open, Bind and Close
« Reply #16 on: August 20, 2008, 06:46:22 AM »
Before even putting it in the IDE, I notice that you are still issuing BindXrefs inside a for loop - move it outside and call it once.

Change is easy - just keep getting a bigger stick until it sticks :D
Me

Glenn R

  • Water Moccasin
  • Posts: 1932
  • What idiot child of married cousins wrote this?!
Re: Open, Bind and Close
« Reply #17 on: August 20, 2008, 09:54:50 AM »
Give this a whirl:

Code: [Select]
using System;
using System.IO;
using System.Runtime.InteropServices;

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

using acadApp = Autodesk.AutoCAD.ApplicationServices.Application;

namespace XrefBind
{
public class Class1
{
[DllImport("acdb17.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode,
EntryPoint = "?acdbBindXrefs@@YA?AW4ErrorStatus@Acad@@PAVAcDbDatabase@@ABV?$AcArray@VAcDbObjectId@@V?$AcArrayMemCopyReallocator@VAcDbObjectId@@@@@@_N22@Z")]
extern public static ErrorStatus acdbBindXrefs(IntPtr pHostDb, IntPtr xrefObjectIds, bool bInsertBind, bool bAllowUnresolved, bool bQuiet);

// Define Command "BAX"
[CommandMethod("tcgsBAX")]
static public void BindAllXrefsCommand()
{
// Get the usual
Document doc = acadApp.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;

// Has the drawing been saved?
if ((short)acadApp.GetSystemVariable("DBMOD") != 0)
{
ed.WriteMessage("{0}Drawing must be saved before continuing - please save the drawing and try again.",
Environment.NewLine);
return;
}

// Dbase for our bind
Database dbBind = null;
ObjectIdCollection xrefIds = null;

try
{
// Create the bind host dbase and read our dwg into it
dbBind = new Database(false, true);
dbBind.ReadDwgFile(db.Filename, System.IO.FileShare.ReadWrite, false, null);

// Resolve any xrefs
dbBind.ResolveXrefs(true, false);

// Get the xref graph for the current dbase...
XrefGraph xrefGraph = dbBind.GetHostDwgXrefGraph(true);
if (xrefGraph == null || xrefGraph.IsEmpty || xrefGraph.NumNodes == 1)
{
ed.WriteMessage("{0}No xrefs found.", Environment.NewLine);
return; // No xrefs...
}

// Not allowing unresolved xrefs, however we could by changing
// 4th argument to true of acdbBindXrefs
if (xrefGraph.MarkUnresolvedTrees())
{
ed.WriteMessage("\nWarning: There are unresolved xrefs - bind aborted!");
return;
}

for (int i = 0; i < xrefGraph.NumNodes; i++)
{
XrefGraphNode xrefGraphNode = xrefGraph.GetXrefNode(i);
if (xrefGraphNode == null)
{
ed.WriteMessage("\nError: Failed to get a node on the graph - aborting!");
return;
}

// Is it the root node, which is the current drawing?
// If it IS, then the number of incoming nodes will be 0...
if (xrefGraphNode == xrefGraph.HostDrawing)
continue;

// Continue if it's truly nested as we can only bind "true" top level parents...
if (xrefGraphNode.IsNested)
continue;

if (xrefGraphNode.NumIn == 1)
{
if (xrefIds == null)
xrefIds = new ObjectIdCollection();

xrefIds.Add(xrefGraphNode.BlockTableRecordId);
}

}//for

ErrorStatus es = ErrorStatus.OK;
// Try to bind
es = acdbBindXrefs(dbBind.UnmanagedObject, xrefIds.UnmanagedObject, true, false, false);

string fullFileName = dbBind.Filename;
string filePath = Path.GetDirectoryName(fullFileName);
string fileName = Path.GetFileNameWithoutExtension(fullFileName);
string timeStamp = DateTime.Now.ToString("yyyy-MM-dd_hh-mm-ss");

string newFileName = Path.Combine(filePath, fileName + "_" + timeStamp + ".dwg");
// try to save
dbBind.RetainOriginalThumbnailBitmap = true;
dbBind.SaveAs(newFileName, DwgVersion.Current);

}
catch (System.Exception ex)
{
ed.WriteMessage("{0}Error: {1}", Environment.NewLine, ex.Message);
}
finally
{
if (dbBind != null)
dbBind.Dispose();
}
}
}
}

Usual disclaimer applies - "all care taken, no responsibility implied". Test on copies of live data etc.
Me

Spike Wilbury

  • Guest
Re: Open, Bind and Close
« Reply #18 on: August 20, 2008, 10:07:40 AM »
As always .... Molto bene.

I have a bunch of functions to be translated to C#.... where can I sent those ones....  :evil:    :-P

Glenn R

  • Water Moccasin
  • Posts: 1932
  • What idiot child of married cousins wrote this?!
Re: Open, Bind and Close
« Reply #19 on: August 20, 2008, 10:13:19 AM »
Thanks Luis...I think ;)

I stewed over the DllImport signature for quite a while. I will have to dig deeper into P/Invoke me thinks.
Me

mcarson

  • Guest
Re: Open, Bind and Close
« Reply #20 on: August 20, 2008, 01:05:28 PM »
no emoticon for speechless?!
How'd you do that?
I think I'll wait till I learn a bit more of the .NET API.

Spike Wilbury

  • Guest
Re: Open, Bind and Close
« Reply #21 on: August 20, 2008, 01:56:47 PM »
no emoticon for speechless?!
How'd you do that?
I think I'll wait till I learn a bit more of the .NET API.



FYI

Glenn is a master :)



Glenn R

  • Water Moccasin
  • Posts: 1932
  • What idiot child of married cousins wrote this?!
Re: Open, Bind and Close
« Reply #22 on: August 20, 2008, 03:59:11 PM »
Thanks for the kind words Luis - I don't get out much ;)

I still remember seeing your lisp code back in the day (and still) and you are the master where that's concerned :)
Me

Glenn R

  • Water Moccasin
  • Posts: 1932
  • What idiot child of married cousins wrote this?!
Re: Open, Bind and Close
« Reply #23 on: August 20, 2008, 04:09:32 PM »
How'd you do that?

20+ years of experience in programming AutoCAD with Lisp, VBA, C++/ARX and .NET. I must admit, the C++/ARX background does help a great deal, as I'm sure Luis, MickD, Chuck, Dan and others can attest to.

Credit where credit is due - Microsoft's rationalisation of all their disparate API's (raw C WIN32, COM/COM+/DCOM, C++, ATL, MFC etc.) into an 'object oriented' API (.NET) is pretty good and is where I focus my efforts nowadays.

I still have a lot to learn though - it's a very big topic...and then throw the ObjectARX/.NET API into the mix and you have even more to cover. If you're embarking on the MCSD route (I was doing this but life/work kept intruding), I wish you luck. Feel free to contact me via the boards or PM if you have questions.
Me

Glenn R

  • Water Moccasin
  • Posts: 1932
  • What idiot child of married cousins wrote this?!
Re: Open, Bind and Close
« Reply #24 on: August 20, 2008, 04:21:54 PM »
As an aside, if you were to combine what I posted above, with this, you would instantly have..........................a 'Batch in-memory Bind' program. However, I would strongly suggest, that you provide some sort of logging to file to indicate any failures that can then be rectified.

Maybe someone will take this idea and post the solution.

Cheers,
Glenn.
Me

Spike Wilbury

  • Guest
Re: Open, Bind and Close
« Reply #25 on: August 20, 2008, 06:35:45 PM »
Thanks for the kind words Luis - I don't get out much ;)

I still remember seeing your lisp code back in the day (and still) and you are the master where that's concerned :)

He he.... and thanks too - but was master of disaster.

But I quit lisp, I use it but very very little on a daily basis.... I lost also the practice BTW :)


mcarson

  • Guest
Re: Open, Bind and Close
« Reply #26 on: August 21, 2008, 07:26:49 AM »
As an aside, if you were to combine what I posted above, with this, you would instantly have..........................a 'Batch in-memory Bind' program. However, I would strongly suggest, that you provide some sort of logging to file to indicate any failures that can then be rectified.

Maybe someone will take this idea and post the solution.

Cheers,
Glenn.

I think I will do this... a week maybe, given the other 'duties' I have to attend to.
Just to give something back...

Glenn R

  • Water Moccasin
  • Posts: 1932
  • What idiot child of married cousins wrote this?!
Re: Open, Bind and Close
« Reply #27 on: August 21, 2008, 12:06:37 PM »

But I quit lisp, I use it but very very little on a daily basis.... I lost also the practice BTW :)


Pretty much the same for me too, Luis.
Me

Glenn R

  • Water Moccasin
  • Posts: 1932
  • What idiot child of married cousins wrote this?!
Re: Open, Bind and Close
« Reply #28 on: August 27, 2008, 12:42:55 PM »
mcarson,

Seeing as you seem to work with a lot of xrefs, you might be interested in Xref States.

Cheers,
Glenn.
Me