Execute

photo credit: Marcin Wichary via photopin cc

As mentioned in the last post, fibers are now inactive in AutoCAD 2015 (the code paths are still there, largely for testing purposes, but should not need to be enabled for typical usage of the product).

Fibers were a technology that Microsoft introduced way back when to help single document (and typically single-threaded) applications adapt more easily to the brave new world of MDI. At least that's my recollection and understanding. They were basically a mechanism by which applications such as AutoCAD could manage their per-document state, making the relevant data current depending on the activated document. I've heard fibers referred to as "manually-scheduled threads", although that's likely to be a simplification of the real situation.

So what does this mean to AutoCAD developers, and why do we care?

Aside from making debugging more predictable – Visual Studio hasn't allowed debugging of applications using fibers for a few releases – this work has brought significant benefits for developers.

The way I understand it – and it's very likely that my understanding is either incomplete or flawed, as I haven't spent a significant amount of time looking at the guts of this mechanism – AutoCAD commands depend on state associated with the current document. Moving away from fibers means the execution context of AutoCAD commands is quite different, but it also brings about opportunities that weren't there before, as we've rationalized the way commands can be called, making them first-class, fully supported ways of making use of the huge amount of pre-existing code inside AutoCAD. Which essentially means AutoCAD developers should no longer feel bad (if they ever did 😉 about calling commands from their code. It's now absolutely valid to do this – it's just as valid to call commands as it is to make use of a lower-level API.

Prior to AutoCAD 2015, you would generally call AutoCAD commands by firing tokens – command names and the user inputs those commands expected – into AutoCAD's input throat. From AutoCAD 2015 onwards, there are two approaches for calling commands: subroutine and coroutine. Subroutine command-calling means that you want to execute a command in its entirety: you know exactly how the command should be called and don't want things to be open-ended. Coroutine command-calling is more open-ended: you don't have all the arguments to provide to the command – and don't know exactly how it's going to proceed – so you're really calling a partial command.

Without fibers acting as a support structure, these two styles of command-calling now need to be handled separately.

In ObjectARX, for instance, you'll no longer find acedCommand() or acedCmd(), you have to use either acedCommandS()/acedCmdS() or acedCommandC()/acedCmdC(), depending on the command-calling style you choose. acedCommandS()/acedCmdS() are easy: they work in much the same way as acedCommand()/acedCmd() used to, but only with complete command/argument sets. acedCommandC()/acedCmdC() are more complicated: you need to provide a callback function that will be called to further process input tokens (it's a form of continuation passing that is very common when dealing with asynchronous method calls, for example). ObjectARX developers should take a look at the ObjectARX Developer's Guide as well as acedCmdNF.h (NF presumably stands for non-fiber in this context) for more information.

So ObjectARX developers have some work to do if they're calling commands in AutoCAD 2015, then. What about the other programming environments?

AutoLISP is much simpler: Autodesk has full control over the "virtual machine" that executes LISP code inside AutoCAD, so we can choose which of the two underlying ObjectARX functions to call, depending on the scenario and without requiring a change in the LISP calling code. That said, the ADN team tells me they've seen scenarios where a developer specifically needed to specify the subroutine style, at which point they've been able to call (command-s …) instead.

For VBA – which has now been updated to VBA 7.1 and is still available as a separate download – I don't think anything has changed: it still has the AcadDocument.SendCommand() method, which seems to work with partial commands (I'll update this post if I hear anything different on that front).

.NET is also simple in its own way: subroutine calls are straightforward – they simply run synchronously via Editor.Command() – and because AutoCAD 2015 now makes use of .NET 4.5 – which provides C# with the async/await mechanism for calling asynchronous methods – we've been able to implement that mechanism for coroutine calls. These now make use of the compiler's automatic callback generation via the await keyword to work asynchronously – e.g. await Editor.CommandAsync(…). You'll need to tag any command method using CommandAsync() with the async modifier, just as you would when using other awaitable methods.

The difference between C# and C++ is analogous to general asynchronous coding: changes have been made at the language level to make asynchrony easier to handle from C#, and in time comparable extensions will make their way into C++ also.

Do bear in mind that to target .NET 4.5 – which is a requirement to use the API enhancements in AutoCAD 2015 – you will need to use Visual Studio 2012 or 2013: VS2010 cannot target .NET 4.5. (ObjectARX developers will have to use the toolset from VS2012 to compile their C++ modules, as that's the compiler being used to build AutoCAD.) I'm personally now using VS2013 as a primary IDE, but make use of the VS2012 toolset when building ObjectARX modules.

If you're still using VS2010, you *should* be able to target your .NET application against the class libraries for AutoCAD 2013 or 2014 (as long as you're not making use of newer APIs) and run that code in AutoCAD 2015, but do make sure you test your application thoroughly.

In tomorrow's post we'll take a look at a new capability related to product theming that has been enabled in AutoCAD 2015.

Update:

To give a sense for the differences between Command() and CommandAsync() when used from C#, here are two commands, one that calls INSERT synchronously with the full set of arguments and one that calls it asynchronously, asking the user to enter the insertion point (a very common scenario, as jigging the block to show the block's graphics is much more complicated than just calling INSERT).

using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.EditorInput;

using Autodesk.AutoCAD.Runtime;

 

namespace CommandCalling

{

  public class Commands

  {

    [CommandMethod("IBS")]

    public void InsertBlockSync()

    {

      var doc =

        Application.DocumentManager.MdiActiveDocument;

      var ed = doc.Editor;

 

      // Our insertion point is hardcoded at 10,10

 

      ed.Command("_.INSERT", "TEST", "10,10", 1, 1, 0);

 

      ed.WriteMessage("\nWe have inserted our block.");

    }

 

    [CommandMethod("IBA")]

    async public void InsertBlockAsync()

    {

      var doc =

        Application.DocumentManager.MdiActiveDocument;

      var ed = doc.Editor;

 

      // Let's ask the user to select the insertion point

 

      await ed.CommandAsync(

        "_.INSERT", "TEST", Editor.PauseToken, 1, 1, 0

      );

 

      ed.WriteMessage("\nWe have inserted our block.");

    }

  }

}

  1. Samir Bittar Rosas Avatar
    Samir Bittar Rosas

    Hi, Kean!

    In .NET, can we still expect the same kind of per-document behavior for instances and session-behavior for static data in classes?

    1. Great question. I need to check on that... I don't think that "session vs. document context" applies in our new fiber-free world, but I'll get clarification from the people who did the work.

      Kean

    2. Kean Walmsley Avatar

      Execution contexts - session & document - are still relevant and supported in the post-fiber world, after all. Things should also work the same with respect to Document.UserData.

      Kean

  2. Hi,kean
    Can you give an example of using Editor.Command() ?

    1. Certainly - will code something up and post later in the week.

      Kean

    2. I've updated the post to show a quick example of how to call the INSERT command both synchronously and asynchronously.

      Kean

  3. Kean - I'm really hoping you will be able to show 3rd party developers how to manage separate icons intended for dark vs. light themes tomorrow.

    1. Not tomorrow but soon. I know Augusto from ADN is looking into this at the moment, so someone will certainly provide a working sample in the coming days.

      Kean

  4. Hi,

    So I assume that C++ ARX code like below also requires the use of acedCommandC or is there some other way?

    acedCommand(RTSTR, _T("_.INSERT"), RTSTR, name, ..., 0);
    for (i = 0; i < nrAttributes; i++) {
    acedCommand(RTSTR, attributes[i], 0);
    }

    1. Kean Walmsley Avatar

      That is correct: you would need to use acedCommandC() or acedCmdC() for this. Or make use of C# (which is much simpler, although Windows-specific) to implement that capability.

      Kean

      1. Hello,

        I tried using acedCommandC to insert symbol with attributes and did not get it to work.

        First the documentation 'acedCommand Migration' section has example code using callbacks like:
        static void myCallbackFn1(void * pData)
        but ARX 2015 headers have
        typedef int (*AcEdCoroutineCallback)(void* pData);

        So I tried code like below. The handler function handleAttributes did not seem to get called at all. acedCommandC returned 5100. After finishing the call sequemce AutoCAD session was messed up as it had lost definition of the command I used to start the test processing. This does not happen when using acedCommandS.

        static int handleAttributes(void * pData)
        {
        TCHAR *val = reinterpret_cast<tchar*>(pData);
        acutPrintf(_T("handleAttributes: '&s'\n"), val != NULL ? val : _T("<null>"));
        if (val != NULL) acedCommandC(&handleAttributes, NULL, RTSTR, val, 0);
        return RTNORM;
        }

        iStatus = acedCommandC(&handleAttributes, _T("test"), RTSTR, _T("_.INSERT"),
        RTSTR, symbol, RT3DPOINT, asDblArray(origin),
        RTSTR, _T("_XYZ"), RTREAL, scale.x, RTREAL, scale.y,
        RTREAL, 1.0, RTREAL, angle, 0);

        1. Kean Walmsley Avatar

          Hi Kari,

          I suggest contacting ADN or posting to the ObjectARX DIscussion Group. Using acedCommandC() is indeed tricky, and I don't have the experience with it to provide help off the top of my head.

          Kean

          1. Hello,

            I found one post in ObjectARX DIscussion Group, where the conclusion was that acedCommandC is not synchronous and so unsuable as my use case functions are callbacks and need to return handle of the created entity.

        2. Amandeep Singh Avatar
          Amandeep Singh

          Hi Kari,

          Tried your above mentioned code snippet.

          I was wondering if you could share some references about porting acedCmdC

          using C++.

          I am trying to port a big application to ACAD 2015, But kind of stuck on acedCmdC.

          I am trying o write a wrapper function like int ads_commandC( int rtype, ... )

          I need more resources and guidelines for coding it because the product is too big....
          Thanks

          1. Kean Walmsley Avatar

            Please post on the ObjectARX discussion group with this kind of request.

            Kean

    2. Kari Heinola Avatar

      The code like above can be actually converted to use acedCmd and so with AutoCAD 2015 AcedCmdS.

      1. Kean Walmsley Avatar
        Kean Walmsley

        Great - glad to hear you got it working.

        Kean

  5. Kean,
    I support a Revit addin but I am not the developer...so I apologize for the the lack of technical specifics in my question. My question is about running Revit as a cloud-based service and using the 2015 API to interact with the service. I understand the idling command has been used since asynchronous interactions were dangerous. Did anything change in 2015 that would allow us to place a version of Revit in the cloud and invoke the Family Editor to create RFA files on the fly? Also, I didn't see anything in the Autodesk 360 offerings that would help facilitate API-driven creation of RFA files. Did I miss something? THANKS!
    - Chris

    1. Chris,

      I don't work with Revit or its API... is it possible you meant to post this question to Jeremy Tammik's blog?

      Regards,

      Kean

      1. Kean, I was actually just communicating with Jeremy about this and was doing more research about the 2015 Revit API. Sorry I didn't notice your specialty wasn't Revit. Thank you for responding!

  6. Dennis Knippel Avatar
    Dennis Knippel

    Hi Kean,

    Excellent to see you still adding great value to these forums. You helped me tremendously a few years back with some customization to the AutoCAD CAD Standards Manager. Today my question is about supporting an old VBA module.

    I've installed VBA 7.1 and compiled said module. However, I notice it uses an instance of Application.GetInterface("VL.Application.16") to implicitly "evaluate lisp expression". Do you happen to know the latest version of this interface? For example: "VL.Application.??".
    OR...
    Should I just replace this legacy VLAX approach with your suggested VBA mechanism of "AcadDocument.SendCommand()"?
    Any insights you might have will be greatly appreciated.
    Regards,
    Dennis Knippel

    1. Kean Walmsley Avatar
      Kean Walmsley

      Hi Dennis,

      Nice to hear from you. 🙂

      The latest version is indeed "VL.Application.16", as far as I can tell.

      But yes, I would suggest using SendCommand() unless you have good reasons not to.

      Regards,

      Kean

      1. Dennis Knippel Avatar
        Dennis Knippel

        Excellent, I will modify the few places that used VLAX to now use the SendCommand() mechanism. Any particular reference/example you could point me to that uses SendCommand() to evaluate a LISP expression?

        1. Dennis Knippel Avatar
          Dennis Knippel

          OR, am I completely clueless and no longer need to evaluate a LISP expression? In other words --> just send the equivalent command. For example: _pedit

          1. Kean Walmsley Avatar
            Kean Walmsley

            If you're just calling a command, then you shouldn't need LISP. But as long as you don't care about any return value, SendCommand() should evaluate LISP just fine, too.

            Kean

            1. Dennis Knippel Avatar
              Dennis Knippel

              Hag sale ant, my friend. Thanks again! 😀

  7. With this new change in 2015 one of my AcadDocument.SendCommand calls that used to work is no longer working. it is a call to run a ".scr" file. The previous command was:

    (command "_.SCRIPT" "C:/Program Files/Company/Company AutoCAD Tools/2015/Scripts/Test.scr")

    I've tried to re-create this using the new Editor.Command method as follows:

    editor.Command("_.SCRIPT", "C:/Program Files/Company/Company AutoCAD Tools/2015/Scripts/Test.scr", 1, 0, 0);

    However, with this I get an eInvalidInput error with no further information. Have you tested the "_.Script" command? Am I using the correct syntax?

    1. Kean Walmsley Avatar

      Is this code being called from an event handler or a modeless dialog, perhaps? I'm guessing it's somehow in the application context rather than a specific document context.

      If that's the case, you might end up having more success with SendStringToExecute(), in case.

      Kean

      1. It is being called from a modeless dialog but I can't use SendStringToExecute because I need it to run synchronously along some c# code that modifies the document.

        1. Kean Walmsley Avatar

          You could also have the script call back into whatever command you want executed when done (or have the SendStringToExecute() call do that, for that matter).

          I suggest posting a more complete sample to the AutoCAD .NET Discussion Group.

          Kean

  8. Eng. Moacir de O. Jr Avatar
    Eng. Moacir de O. Jr

    I'm having trouble migrating this command to arx 2015

    acedCommand to acedCommandS or acedCommandC, please help me:

    static int ads_cmd_son(void)

    {

    struct resbuf *rb = acedGetArgs () ;

    int osmodo;

    ACHAR auxt[30];

    struct resbuf rb1;

    acedGetVar(_T("OSMODE"), &rb1);

    osmodo = rb1.resval.rint;

    rb1.resval.rint = 0;

    acedSetVar(_T("OSMODE"), &rb1);

    while (rb != NULL) {

    if(rb->restype == RTREAL) {

    acdbRToS(rb->resval.rreal,2,8,auxt);

    acedCommand(RTSTR, auxt, RTNONE);

    }

    if(rb->restype == RTPOINT) acedCommand(rb->restype, rb->resval.rpoint, RTNONE);

    if(rb->restype == RTSHORT) {

    acdbRToS((ads_real)rb->resval.rint,2,0,auxt);

    acedCommand(RTSTR, auxt, RTNONE);

    }

    if(rb->restype == RTANG) {

    acdbRToS(rb->resval.rreal,2,8,auxt);

    acedCommand(RTSTR, auxt, RTNONE);

    }

    if(rb->restype == RTSTR) acedCommand(rb->restype, rb->resval.rstring, RTNONE);

    if(rb->restype == RTENAME) acedCommand(rb->restype, rb->resval.rlname, RTNONE);

    if(rb->restype == RTPICKS) acedCommand(rb->restype, rb->resval.rlname, RTNONE);

    if(rb->restype == RTORINT) {

    acdbRToS(rb->resval.rreal,2,8,auxt);

    acedCommand(RTSTR, auxt, RTNONE);

    }

    if(rb->restype == RT3DPOINT) acedCommand(rb->restype, rb->resval.rpoint, RTNONE);

    if(rb->restype == RTLONG) {

    acdbRToS(rb->resval.rlong,2,0,auxt);

    acedCommand(RTSTR, auxt, RTNONE);

    }

    rb = rb->rbnext;

    }

    rb1.resval.rint = osmodo;

    acedSetVar(_T("OSMODE"), &rb1);

    if ( rb != NULL )

    acutRelRb (rb) ;

    return (RSRSLT) ;

    }

    1. Kean Walmsley Avatar

      Sorry - I don't provide support in this way (I really don't have time).

      I see Owen's point in his forum response: if you want someone to convert it for you, it helps to explain what specifically you've tried and what isn't working. Otherwise it's just asking for free development services.

      Kean

  9. Hi Kean, hi all. Why I don't get that option of ed.command()? am I using a different assembly? I really don't know what is going on, could you please help me, I'm using AutoCAD 2013 and Visual Studio 2013. The reference I've in my project are... accoremgd, acdbmgd and acmgd.

    Well let me explain my problem, I'm creating a .net program that generates my DLL for Autocad, and create a LISP that loads the DLL and executes the command and I put it on the start up suite of AutoCAD, the thing is that I want my dll to call a previous LISP loaded. I've try sendStringToExecute but it is not working, and now I want to use ed.command() but I don't get that option. Hope you can help me! Tnks

    1. Hi Daniel,

      The clue is in the title of the post (where it says "AutoCAD 2015").

      Have you tried Application.Invoke()?

      Regards,

      Kean

  10. Great Information....Kean really gives some old school methods new life.

    1. Hi Kean,
      This sounds great - I've been using Doc.SendStringToExecute() successfully up till now, but I can't get the same commands to work with Ed.Command (AutoCAD crashes). I am assuming where \n was used this Is a new parameter to Command(). I am trying to execute the SCALE command on a selected object:
      Ed.Command("_.SCALE", "10,10,0", 100);
      Not sure if the scale factor should be in quotes but have tried both unsuccessfully.

      1. Hi Paul,

        The scale factor shouldn't need to be in quotes... are you sure the pickfirst selection wasn't cleared in your command (it needs the right command flag - UsePickFirst, I think)?

        Or perhaps you're setting the pickfirst selection manually.

        Anyway - I'd need to see more code to understand what's wrong (best is to post to the discussion groups and then post the link here).

        Cheers,

        Kean

        1. Hi Kean,
          Thanks v much for your reply. Not sure what you mean about "..right command flag.." Is this an argument in Command()?

          1. Hi Paul,

            I assume you're calling the command from your own command (which can have command-flags assigned in the CommandMethod() attribute).

            Again, easier to see more complete code, if possible.

            Kean

            1. Hi Kean,

              Here is the code - same as I posted on the context menu discussion- modified to use Ed.Command(). A simple polyline shape is selected in the model space and the context menu is used to execute "Scale 2" which works or "Scale 1" which crashes:

              public class CountMenu

              {

              private static ContextMenuExtension cme;

              public static void Attach()

              {

              if (cme == null)

              {

              cme = new ContextMenuExtension();

              MenuItem mi = new MenuItem("Paul's menu");

              cme.MenuItems.Add(mi);

              MenuItem mi_1 = new MenuItem("Scale 1");

              mi_1.Click += OnScale;

              mi.MenuItems.Add(mi_1);

              MenuItem mi_2 = new MenuItem("Scale 2");

              mi_2.Click += OnItem2;

              mi.MenuItems.Add(mi_2);

              RXClass rxc = Entity.GetClass(typeof(Entity));

              Application.AddObjectContextMenuExtension(rxc, cme);

              }

              }

              public static void Detach()

              {

              RXClass rxc = Entity.GetClass(typeof(Entity));

              Application.RemoveObjectContextMenuExtension(rxc, cme);

              }

              private static void OnScale(Object o, EventArgs e)

              {

              Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;

              ed.Command("SCALE", "12,12,0", 100);

              }

              private static void OnItem2(Object o, EventArgs e)

              {

              Document doc = Application.DocumentManager.MdiActiveDocument;

              doc.SendStringToExecute("SCALE\n12,12,0\n100\n", true, false, false);

              doc.SendStringToExecute("ZOOM\n0.01\n", true, false, false);

              }

              }

              1. Ah, OK - I should have connected this with your context menu question. You're in the session context, so you'll need to manually lock the document before calling the command.

                Kean

                1. Hi Kean,

                  I added:

                  using (ed.Document.LockDocument())
                  {
                  ed.Command("SCALE", "12,12,0", 100);
                  }

                  but still no joy - Exception eInvalidInput. Am I missing some flags?

                  1. Hi Paul,

                    I see the error as well, but can't see how to avoid it (other than sticking with SendStringToExecute()).

                    You might want to post this via ADN or the discussion groups, to see whether someone there has time to research it.

                    Regards,

                    Kean

                    1. Hi Kean,
                      Glad its not just me :-). There are other solutions to synchronous commands in the 2015 documentation but yours was much neater - in fact it doesn't even seem to be documented!
                      Synchronous is essential if you are running several commands that rely on the previous result so I am surprised there is not more made of it.
                      Thanks again for your posts I always find them helpful.
                      Regards
                      Paul

  11. how to send Enter in ediotr.Command?

    1. I've simply used the empty string ("") as an argument for enter.

      Kean

  12. Hi Paul,

    With AutoCAD 2016 there's finally a way to make this working without SendStringToExecute():

    keanw.com/2015/03/autocad-2016-calling-commands-from-autocad-events-using-net.html

    Regards,

    Kean

  13. Thanks Kean that's good news 🙂

  14. Gabriel Potestades Avatar
    Gabriel Potestades

    Hi Kean!

    Is possible to use Revision Cloud in this situation? Example: Creating a polyline/circle/ellipse then make it a revision cloud.

    Thank you!

    1. Hi Gabriel,

      Yes, certainly: you can create the entity and then use "_-REVCLOUD" "" "_L" "".

      Regards,

      Kean

      1. Gabriel Potestades Avatar
        Gabriel Potestades

        Hi Kean,

        If it's not much trouble, in the Editor.Command(). I'll put the revcloud like this, Editor.Command("_-REVCLOUD" "" "_L" ""). But where do I insert the entity I just created in this part of the code?

        Regards.

        1. Hi Gabriel,

          The "_L" selects it. The simplest way is to create the entity with one call to Editor.Command() and then the REVCLOUD directly afterwards.

          Regards,

          Kean

          1. Gabriel Potestades Avatar
            Gabriel Potestades

            I have research and found out that you can call that latest entity you created but my code doesn't seem to work. The error is in the ed.Command line. Sorry, I'm new to plugins.

            Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor

            Dim db As Database = Application.DocumentManager.MdiActiveDocument.Database

            Dim entlast As ObjectId = Autodesk.AutoCAD.Internal.Utils.EntLast()

            Using acTrans As Transaction = db.TransactionManager.StartTransaction

            Dim acent As Entity = acTrans.GetObject(entlast, OpenMode.ForWrite)

            ed.Command("_-REVCLOUD", "", acent, "")

            End Using

            Regards!

            1. You can either create the object and pass it via a SelectionSet to the command, or you can use the "_L" (short for "_LAST") keyword. I'll write a blog post to explain.

              Kean

              1. Gabriel Potestades Avatar
                Gabriel Potestades

                I'll wait for the blog post cause I'll know it's more in-depth

                Thank you!

  15. Gabriel Potestades Avatar
    Gabriel Potestades

    Thank you for the guide!

    I forgot to ask, how to set the style to Calligraphy? Is it included in the Editor.Command()?

    Regards.

    1. Hi Gabriel,

      Please use the discussion groups for these questions... this is really more general support (something which I discourage people from asking me for).

      forums.autodesk.com

      Regards,

      Kean

      1. Gabriel Potestades Avatar
        Gabriel Potestades

        Ok. Thank you very much!

  16. Hi kean
    I need to edit the block attribute via send command using AutoCAD API, Is it possible?
    If yes can you please provide me a solution.

    1. Hi jagan,

      Please post your support questions to the AutoCAD .NET forum:

      forums.autodesk.com/

      Kean

  17. Hi Mr Kean, thank you very much for this post. in the above code you are using the ed.Command() method. but there is also the ed.SendStringToExecute() method:

    (1) do they both do the same thing?
    (2) is it advantageous to do use one over the other?
    (3) also is it faster to use the Command and/or SendStringToExecute method than if we were performing the same operation through other API calls?

    your answers much appreciated

    rgds, Ben

    1. Hi Ben,

      I'm on an extended trip with my family: please post your question via the AutoCAD .NET forum to get help with this.

      Many thanks,

      Kean

  18. yes Humans need those jobs but with over regulation and "One size fits all" blanket "solutions"
    animalsbirds.com/ame...
    like minimum wage, etc. look for more automated workers in every industry.

  19. shrikant deshpande Avatar
    shrikant deshpande

    Hi Kean,
    I want to automatically invoke a command as soon as we load our dll using NETLOAD.
    I dont want to type it manually.
    Is there any way?
    Thank you

  20. shrikant deshpande Avatar
    shrikant deshpande

    Thank You

  21. Daniel Gilliland Avatar

    when i use await ed.CommandAsync(

    "_.INSERT", "TEST", Editor.PauseToken, 1, 1, 0);

    but leave out the angle the rest of the program runs before i can set an angle and additional attributes for my dynamic block

    1. Is this a question? If so, please feel free to post it on the AutoCAD developer forums.

      Kean

    2. Never mind, I didn't realise PauseToken was a placeholder for parameters. Just put PauseToken into where 0 is and it works great!

Leave a Reply to Ben Cancel reply

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