Run (acet-edittime-total) LISP from edittime.ARX in Dotnet and retreive result

Run (acet-edittime-total) LISP from edittime.ARX in Dotnet and retreive result

albarney99
Advocate Advocate
2,010 Views
8 Replies
Message 1 of 9

Run (acet-edittime-total) LISP from edittime.ARX in Dotnet and retreive result

albarney99
Advocate
Advocate

Hi

The main issue I am having is running an existing LISP routine from VB.net and retrieving the result of that LISP.

 

I am trying to move all of my Save LISP function into Dotnet. I need the (acet-edittime-total) value to write to Vault as part of a save routine.

This is loaded from the edittime.arx.

I can run it as a lisp from VB.net ok but it just writes the result to the command line.

I can't find a way to run a lisp function from inside Dotnet and get the result back.

I know I can create a LISP function in VB.net and run that and get results but this is not that scenario. I have to run an external lisp.

 

I have tried wrapping the ARX but I don't really get how that works and the documentation for Express Tools is pretty much non existant.

 

I hve tried this but it just returns 0 and without the my_cmd string the same result. Running the dumpbin on the edittime.arx only gives the acrxEntryPoint result for commands available.

 

Edittime_ARX("(acet-edittime-total)")

<DllImport("C:\Program Files\Autodesk\AutoCAD 2017\Express\edittime.arx", CallingConvention:=CallingConvention.Cdecl, CharSet:=CharSet.Unicode, EntryPoint:="acrxEntryPoint")> Public Function Edittime_ARX(ByVal my_cmd As String) As Decimal End Function

I can get it using the COPYHIST and Clipboard.GetText() but to me that seems cumbersome. Another optiojn is to write it to a text file and get it from that but again that is cumbersome and potential for locked files etc causing it to fall over.

0 Likes
Accepted solutions (1)
2,011 Views
8 Replies
Replies (8)
Message 2 of 9

ActivistInvestor
Mentor
Mentor

@albarney99 wrote:

Hi

The main issue I am having is running an existing LISP routine from VB.net and retrieving the result of that LISP.

 

I am trying to move all of my Save LISP function into Dotnet. I need the (acet-edittime-total) value to write to Vault as part of a save routine.

This is loaded from the edittime.arx.

I can run it as a lisp from VB.net ok but it just writes the result to the command line.

I can't find a way to run a lisp function from inside Dotnet and get the result back.

I know I can create a LISP function in VB.net and run that and get results but this is not that scenario. I have to run an external lisp.

 

I have tried wrapping the ARX but I don't really get how that works and the documentation for Express Tools is pretty much non existant.

 

I hve tried this but it just returns 0 and without the my_cmd string the same result. Running the dumpbin on the edittime.arx only gives the acrxEntryPoint result for commands available.

 

Edittime_ARX("(acet-edittime-total)")

<DllImport("C:\Program Files\Autodesk\AutoCAD 2017\Express\edittime.arx", CallingConvention:=CallingConvention.Cdecl, CharSet:=CharSet.Unicode, EntryPoint:="acrxEntryPoint")> Public Function Edittime_ARX(ByVal my_cmd As String) As Decimal End Function

I can get it using the COPYHIST and Clipboard.GetText() but to me that seems cumbersome. Another optiojn is to write it to a text file and get it from that but again that is cumbersome and potential for locked files etc causing it to fall over.


From the looks of the functions from edittime.arx, they are not doing very much aside from wrapping a timer that can be started, stopped, paused, resumed, and reset. Or perhaps there's more to it than that?

 

Can you describe what those functions do and how you use them?

 

 

0 Likes
Message 3 of 9

albarney99
Advocate
Advocate

edittime.arx is a Standard Express Tools function supplied with AutoCAD.

The DllImport was my attempt to to get access to it (unsuccessfully).

 

EDITTIME (Express Tool) Information

 

(acet-edittime-total) is one of the available functions from the arx.

 

All it does is return a decimal vaue of the current edittime total to the command line. That is the value I need to get.

 

 Capture.PNG

 

We use it to find the time the drawing has been actually editted for (not the time it has been opened for).

0 Likes
Message 4 of 9

ActivistInvestor
Mentor
Mentor

You don't need to call any LISP functions from your .NET extension to get the value you need.

 

The value is stored in the DWG file, in an XRecord that's contained in a DBDictionary.

 

The thing is that the stored value is only updated when the file is saved, so assuming that you 

either just opened the file, or can save it before accessing it, the value can be gotten using the

code below (visit http://converter.telerik.com to convert it to VB.NET):

 

public static class Class1
{

   [CommandMethod("EDITTIME_TOTAL")]
   public static void GetEditTimeTotal()
   {
      Document doc = Application.DocumentManager.MdiActiveDocument;
      Editor ed = doc.Editor;
      double result = GetAcetEditTimeTotal(doc.Database);
      ed.WriteMessage("\nACET_EDITTIME_TOTAL: {0}", result);
   }

   public static double GetAcetEditTimeTotal(Database db)
   {
      using(var tr = new OpenCloseTransaction())
      {
         try
         {
            DBDictionary nod = (DBDictionary) tr.GetObject(db.NamedObjectsDictionaryId, OpenMode.ForRead);
            if(nod.Contains("BNS_VARIABLES"))
            {
               DBDictionary dict = (DBDictionary) tr.GetObject(nod.GetAt("BNS_VARIABLES"), OpenMode.ForRead);
               if(dict.Contains("BNS_EDITTIME_TOTAL"))
               {
                  Xrecord xrec = (Xrecord) tr.GetObject(dict.GetAt("BNS_EDITTIME_TOTAL"), OpenMode.ForRead);
                  TypedValue tv = xrec.Data.Cast<TypedValue>().FirstOrDefault();
                  if(tv.TypeCode == 40)
                     return (double) tv.Value;
               }
            }
            return 0.0;
         }
         finally
         {
            tr.Commit();
         }
      }
   }

}

 


@albarney99 wrote:

edittime.arx is a Standard Express Tools function supplied with AutoCAD.

The DllImport was my attempt to to get access to it (unsuccessfully).

 

EDITTIME (Express Tool) Information

 

(acet-edittime-total) is one of the available functions from the arx.

 

All it does is return a decimal vaue of the current edittime total to the command line. That is the value I need to get. 

 

We use it to find the time the drawing has been actually editted for (not the time it has been opened for).


 

Message 5 of 9

albarney99
Advocate
Advocate

Only just got back on to this. Thanks for the prompt response.

 

That does work as advertised and can get that value ok

 

But.... (there is always a but)

 

What i am trying to do it to update the drawing Title Block and update the Vault properties BEFORE I save the drawing (ie using the beginsave event). To use this value I have to save the drawing, do the update, then resave. i would prefer to not have to do this.

 

Is there a way to update this value without saving or again getting the value of (acet-edittime-total).

 

I ran the (acet-edittime-total) function before getting the BNS_EDITTIME_TOTAL value but BNS_EDITTIME_TOTAL it is not updated running that lisp.

Thanks in advance for any help.

0 Likes
Message 6 of 9

kerry_w_brown
Mentor
Mentor

@albarney99 wrote:

 

<...>

 

Is there a way to update this value without saving or again getting the value of (acet-edittime-total).

 

 

<....>

 

 

I can't envision a way to do it.

 

As mentioned by  @ActivistInvestor and noted in the documentation the data recorded reflects the values at the last save:

>>>

AutoLISP Access

EDITTIME-related data is stored per drawing in the Named Object Dictionary. The (acet-getvar ...) and (acet-setvar ...) functions, which are available in the acetutil.fas module, provide access to the BNS_EDITTIME_TOTAL profile variable. If EDITTIME has been enabled in a drawing, you can use (acet-getvar '("BNS_EDITTIME_TOTAL")) to extract the elapsed time (up to the opening of the current editing session) from the current drawing as a Julian time value (a REAL value, containing the number of 24-hour days the drawing has been in active use).

<<<


// Called Kerry or kdub in my other life.

Everything will work just as you expect it to, unless your expectations are incorrect. ~ kdub
Sometimes the question is more important than the answer. ~ kdub

NZST UTC+12 : class keyThumper<T> : Lazy<T>;      another  Swamper
0 Likes
Message 7 of 9

ActivistInvestor
Mentor
Mentor
Accepted solution

@albarney99 wrote:

Only just got back on to this. Thanks for the prompt response.

 

That does work as advertised and can get that value ok

 

But.... (there is always a but)

 

What i am trying to do it to update the drawing Title Block and update the Vault properties BEFORE I save the drawing (ie using the beginsave event). To use this value I have to save the drawing, do the update, then resave. i would prefer to not have to do this.

 

Is there a way to update this value without saving or again getting the value of (acet-edittime-total).

 

I ran the (acet-edittime-total) function before getting the BNS_EDITTIME_TOTAL value but BNS_EDITTIME_TOTAL it is not updated running that lisp.

Thanks in advance for any help.


Try this:

 

public static class Class1
{

   [CommandMethod("EDITTIME_TOTAL")]
   public static void TestEdTime()
   {
      Document doc = Application.DocumentManager.MdiActiveDocument;
      Editor ed = doc.Editor;
      double result = GetAcetEditTimeTotal();
      ed.WriteMessage("\nACET_EDITTIME_TOTAL: {0}", result);
   }

   public static double GetAcetEditTimeTotal()
   {
      Document doc = Application.DocumentManager.MdiActiveDocument;
      Database db = doc.Database;
      using(doc.LockDocument())
      {
         // In order to coerce EDITTIME.ARX to update the value
         // it stores it the drawing file, we emulate what the
         // AUTOSAVE mechanism does, by saving the database to a 
         // temporary file. Doing that triggers the notification 
         // EDITTIME.ARX uses to update the value it stores in
         // the drawing file. This does not save the database to 
         // the filename of the active document or affect it in 
         // any other way, since it also discards changes to its 
         // DBMOD flags. In order for this to work, EDITTIME.ARX
         // must be loaded. Otherwise, the value returned will be
         // the value that was saved in the DWG file, the last
         // time the file was saved while EDITTIME.ARX was loaded.

         if(Convert.ToInt32(Application.GetSystemVariable("DBMOD")) > 0)
         {
            var tempfilename = System.IO.Path.GetTempFileName();
            doc.PushDbmod();
            db.SaveAs(tempfilename, db.OriginalFileVersion);
            doc.PopDbmod();
            File.Delete(tempfilename);
         }
         using(var tr = new OpenCloseTransaction())
         {
            try
            {
               DBDictionary nod = (DBDictionary) tr.GetObject(db.NamedObjectsDictionaryId, OpenMode.ForRead);
               if(nod.Contains("BNS_VARIABLES"))
               {
                  DBDictionary dict = (DBDictionary) tr.GetObject(nod.GetAt("BNS_VARIABLES"), OpenMode.ForRead);
                  if(dict.Contains("BNS_EDITTIME_TOTAL"))
                  {
                     Xrecord xrec = (Xrecord) tr.GetObject(dict.GetAt("BNS_EDITTIME_TOTAL"), OpenMode.ForRead);
                     TypedValue tv = xrec.Data.Cast<TypedValue>().FirstOrDefault();
                     if(tv.TypeCode == 40)
                        return (double) tv.Value;
                  }
               }
               return 0.0;
            }
            finally
            {
               tr.Commit();
            }
         }
      }
   }

}

Message 8 of 9

kerry_w_brown
Mentor
Mentor

Thanks ActiveInvestor,

clever fudge 🙂

 

Regards,

 


// Called Kerry or kdub in my other life.

Everything will work just as you expect it to, unless your expectations are incorrect. ~ kdub
Sometimes the question is more important than the answer. ~ kdub

NZST UTC+12 : class keyThumper<T> : Lazy<T>;      another  Swamper
0 Likes
Message 9 of 9

albarney99
Advocate
Advocate

Thanks. This did work.

Whilst not ideal I think that is as good as I am going to get. It would be nice if Autodesk opened these functions up to be able to be used outside of the LISP world.

0 Likes