Running Commands Using the API

Occasionally there is a need to run an Inventor command from a program.  There are a couple of reasons why you might want to do this.  One is when the API doesn’t support some functionality but Inventor does.  By running the command you can sometimes work around the API deficiency.  Another reason is when you want to take advantage of the interactive behavior of a command by starting a command and then turning it over to the user finish it.

Running a Command in Inventor
It turns out that it’s fairly simple to run any command in Inventor.  This includes Inventor’s standard commands and also Add-In commands.  In the API, every command is represented as a ControlDefinition object.  The ControlDefinition object supports the Execute method which is the equivalent of clicking on a button and running a command in the user-interface.  Below is an example that executes the Line command in a sketch.

Public Sub RunLineCommand()        ' Get the CommandManager object.            Dim oCommandMgr As CommandManager         Set oCommandMgr = ThisApplication.CommandManager             ' Get control definition for the line command.            Dim oControlDef As ControlDefinition         Set oControlDef = oCommandMgr.ControlDefinitions.Item( _                                                      "SketchLineCmd")      ' Execute the command.         Call oControlDef.Execute     End Sub

 

Getting Command Names
The tricky part in using the code above is knowing what the name of the command is that you want to run.  In the example above it uses “SketchLineCmd” to specify the Line command.  Every control definition has a name that uniquely identifies it.  There are a couple of techniques you can use to find out the name of the desired command.  The first is to use a program to create a list of all of the available commands.  The program below, (which is straight from Inventor’s programming help), does this.  It will create a file named “C:TempCommandNames.txt” that contains a list showing the name and description of every command.  You can open this file using Notepad or another text editor and search for the command you’re interested in.  Command names are typically very similar to the command name you see in the user-interface.

Sub PrintCommandNames()        ' Get the CommandManager object.            Dim oCommandMgr As CommandManager         Set oCommandMgr = ThisApplication.CommandManager             ' Get the collection of control definitions.            Dim oControlDefs As ControlDefinitions         Set oControlDefs = oCommandMgr.ControlDefinitions             ' Open the file and print out a header line.            Dim oControlDef As ControlDefinition         Open "C:tempCommandNames.txt" For Output As #1         Print #1, Tab(10); "Command Name"; Tab(75); _                   "Description"; vbNewLine             ' Iterate through the controls and write out the name.          For Each oControlDef In oControlDefs             Print #1, oControlDef.InternalName; Tab(55); _                       oControlDef.DescriptionText         Next             ' Close the file.          Close #1     End Sub

Another technique to find a command name is to use the Event Watcher utility that’s delivered as part of Inventor’s SDK.  This utility lets you listen to the various events that Inventor supports through the API.  One of these events is sent whenever a command is executed within Inventor and as part of that event it provides the name of the command that was executed.  To use this follow the steps below.

  1. Have Inventor running and in a state where the command you want to use is available.  For example, if you want to know the name of the Circle command you will need to have a sketch active.
  2. Run EventWatcher.exe.  On a Windows Vista install this is typically at:

    C:UsersPublicDocumentsAutodeskInventor 2009SDKDeveloperToolsToolsEventWatcherbinRelease

    On a Windows XP install it is typically at:

    C:Program FilesAutodeskInventor 2009SDKDeveloperToolsToolsEventWatcherbinRelease

    If you can’t find it, it’s likely you haven’t installed the developer tools portion of the SDK.  To do that install DeveloperTools.msi, which is in the SDK directory.  If you’re running Vista you’ll need to disable UAC to successfully install the developer tools.
  3. In EventWatcher, find the event UserInputEvents.OnActivateCommand and make sure the event has a check mark beside it.
  4. Run the whatever command in Inventor that you want to find the name for.
  5. Get the command name from EventWatcher.  The picture below shows the EventWatcher interface with the OnActivateCommand selected and the results after running the New Sketch and Sketch Line commands.

EventWatcher

 

Limitations
Being able to run any command using the API may seem like the answer to the problem where the API doesn’t cover all of Inventor’s functionality.  Unfortunately this isn’t a solution to that problem.  When you execute a command using the functionality discussed above it is exactly the same as if you had clicked on the command in the user-interface; the command is started.  The problem is that most commands need additional input from the user.  For example, the Extrude command displays a dialog to get the required input from the user or the Arrange Dimensions command doesn’t have a dialog but does require the user to select the set of dimensions to arrange.

In general, when running a command using the API you can’t provide the input the command is expecting so you can’t fully control and use
the command via the API.  There are a couple of exceptions to this discussed below but for most commands you can only start them through the API.  This is still useful because there are cases where you only want to start a command and then let the user take over.

Providing Input to Commands
As mentioned above, there are some exceptions about providing input to commands that will allow you to better utilize them from the API.  There are two techniques of providing input to a command.  The first is pre-selecting the entities that the command should process.  This will only work for a small set of commands but is a workaround in a few cases where the API doesn’t directly support the equivalent of the command functionality.

An example of the use of pre-selecting entities is the new Arrange Dimensions command in Inventor 2010.  The API doesn’t support this functionality yet but by using this pre-selection technique you can use the command directly.  You select entities by adding them to the SelectSet object.  This is the equivalent of the user selecting them.  Many commands will check to see if valid entities are selected and operate on them if they are.  The program below takes advantage of this. 

Public Sub ArrangeDimensions()        ' Get the active document, assuming it is a drawing.            Dim oDrawDoc As DrawingDocument         Set oDrawDoc = ThisApplication.ActiveDocument             ' Get the collection of dimensions on the active sheet.            Dim oDimensions As DrawingDimensions         Set oDimensions = oDrawDoc.ActiveSheet.DrawingDimensions             ' Get a reference to the select set and clear it.            Dim oSelectSet As SelectSet         Set oSelectSet = oDrawDoc.SelectSet         oSelectSet.Clear             ' Add each dimension to the select set to select them.            Dim oDrawDim As DrawingDimension         For Each oDrawDim In oDimensions             oSelectSet.Select oDrawDim         Next            ' Get the CommandManager object.            Dim oCommandMgr As CommandManager         Set oCommandMgr = ThisApplication.CommandManager             ' Get control definition for the arrange dimensions command.              Dim oControlDef As ControlDefinition           Set oControlDef = oCommandMgr.ControlDefinitions.Item( _                                  "DrawingArrangeDimensionsCmd")         ' Execute the command.              Call oControlDef.Execute       End Sub

 

In the case of the Arrange Dimensions sample above, it fully completes the command.  That is when you run the macro, all of the dimensions on the active sheet will be re-arranged.  That’s because if the command sees some dimensions in the select set it operates on them without asking for any more input.  Most commands, even if they support pre-selection of entities, will still allow additional selection so they will still require user input.  For example the Fillet command will take any pre-selected edges as input but still displays the dialog to allow the user to select more edges and specify any other options.

There is another way of providing input for most commands expect a filename as input.  Through the API you can predefine a filename and then run the command.  If a filename is defined, the command will use it.  For some commands, where only a filename is needed, it will skip the dialog portion of the command, for example the Place Component command.  Where more information is required it will use the predefined filename as the default filename and the command will run as normal by displaying its dialog so the user can change the filename and/or set other options.  The Base View command that’s used to create a drawing view is a good example of this.

You predefine a filename using the PostPrivateEvent method of the CommandManager object.  The example below demonstrates its use with the Place Component command.  When the macro executes the Place Component command checks to see if a filename has already been defined.  If it has it uses that filename and skips the dialog step and continues to the step where the user can specify the placement point of the component.  This is a good example of defining the inputs and then allowing the command to take over so you can take advantage of the interactivity the command provides.

Public Sub PlacePart()        ' Get the command manager.            Dim oCommandMgr As CommandManager         Set oCommandMgr = ThisApplication.CommandManager             ' Post the filename.            Call oCommandMgr.PostPrivateEvent(kFileNameEvent, _              "C:UsersekinsbDocumentsInventor 2010Showcasetest.ipt")             ' Get control definition for the place component command.            Dim oControlDef As ControlDefinition         Set oControlDef = oCommandMgr.ControlDefinitions.Item( _                                      "AssemblyPlaceComponentCmd")          ' Execute the command.            Call oControlDef.Execute     End Sub

 

Command Execution Behavior

In all of the examples above the Execute method has been used to run the desired command.  The behavior of this method is to tell Inventor to run the command but immediately return control back to your program.  In the example of placing a component in the assembly, control returns back to the macro right after calling Execute, event though the user is still in the middle of placing components.  In many cases this is ok because it’s likely this is the last step in your program, but sometimes you may want to wait until the command has been completed and then finish some additional steps in your program.  You can do this using the Execute2 method.  This method has a single argument indicating if you want to run the command synchronously or asynchronously.  Asynchronous is the same as the Execute method and will immediately return control back to your program.  Synchronous won’t ret
urn control back to your program until the command has finished processing. 

Here’s a variation of the previous program that reports on which components were just placed.

Public Sub PlacePart2()        ' Get the assembly component definition.            Dim oAsmDef As AssemblyComponentDefinition         Set oAsmDef = ThisApplication.ActiveDocument.ComponentDefinition             ' Get the command manager.            Dim oCommandMgr As CommandManager         Set oCommandMgr = ThisApplication.CommandManager             ' Post the filename.            Call oCommandMgr.PostPrivateEvent(kFileNameEvent, _               "C:UsersekinsbDocumentsInventor 2010Showcasetest.ipt")             ' Get control definition for the place component command.            Dim oControlDef As ControlDefinition         Set oControlDef = oCommandMgr.ControlDefinitions.Item( _                                      "AssemblyPlaceComponentCmd")             ' Get the current number of occurrences.              Dim iOccurrenceCount As Long           iOccurrenceCount = oAsmDef.Occurrences.Count            ' Execute the command synchronously.      Call oControlDef.Execute2(True)                 ' Display information about the placed components.              Dim strPrompt As String           strPrompt = oAsmDef.Occurrences.Count - iOccurrenceCount & _                                  " occurrences were placed:" & vbCr           Dim i As Integer           For i = iOccurrenceCount + 1 To oAsmDef.Occurrences.Count               strPrompt = strPrompt & "    " & _                           oAsmDef.Occurrences.Item(i).Name & vbCr           Next           MsgBox strPrompt       End Sub

Comments

7 responses to “Running Commands Using the API”

  1. Vladimir Ananiev Avatar
    Vladimir Ananiev

    Thank you, Brian, for this post.
    In Inventor 2009 Execute2(True) doesn’t work as described.
    So I still have to use loop like
    Do While ThisApplication.CommandManager. _
    ActiveCommand=”AssemblyPlaceComponentCmd”
    DoEvents
    Loop
    Is Execute2 method specific to Inventor 2010 release?
    Vladimir

  2. Raminder Singh Avatar
    Raminder Singh

    Hi Vladimir,
    I’ve Inventor 2009 and its api also exposes Execute2 method. So it’s not specific to 2010.

  3. Hello, I’m using the below code in an activated sketch, yet nothing seems to happen. Are there specific different commands when using SketchProjectCutEdgescmd?
    Dim oDef As ControlDefinition
    Set oDef = ThisApplication.CommandManager.ControlDefinitions.Item(“SketchProjectCutEdgesCmd”)
    oDef.Execute

  4. Brian Ekins Avatar
    Brian Ekins

    Here’s some code that I’ve copied from a program I had previously written that does exactly what you’re trying to do. I don’t remember why I set the SilentOperation property.
    ‘ Create a sketch on the work plane.
    Dim invSketch As PlanarSketch
    Set invSketch = PartCompDef.Sketches.Add(invWorkPlane)
    ‘ Call the Project Cut Edges command.
    invSketch.Edit
    ThisApplication.SilentOperation = True
    ThisApplication.CommandManager.ControlDefinitions.Item(“SketchProjectCutEdgesCmd”).Execute
    ThisApplication.SilentOperation = False
    invSketch.ExitEdit
    ThisApplication.ActiveView.Update

  5. Cristiano Avatar
    Cristiano

    Hi,
    Use your example PlacePart with command RenameBrowserNodes and pre-setting Default Option.
    How I use the kCommandNameEvent and define in the option?
    Call oCommandMgr.PostPrivateEvent(kCommandNameEvent, “Default”)

  6. Brian,
    I have an odd situation. I’m using the the CommandManager to execute an export of a face to get to a pline of the surface’s edges in Autocad (which is used by a vendor to create an extrusion die). Here’s the applicable portion of the code (in c#):
    partDoc: previously assigned to the active Part Document.
    dieProfile: previously selected by the user via user interactions (type Inventor.Face).
    partDoc.SelectSet.Clear();
    partDoc.SelectSet.Select(dieProfile);
    controlDef = commandManager.ControlDefinitions[“GeomToDXFCommand”];
    controlDef.Execute();
    The code above runs correctly when my program runs as an external program that hooks into an existing instance of Inventor. The problem is that whenever I convert my program to run as an add-in the exact same code above doesn’t appear to execute (or at least the export never happens). Any ideas?

  7. […] ※本記事は、「Running Commands Using the API」から、転写・意訳・補足したものです。 […]

Leave a Reply

Discover more from Autodesk Developer Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading