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.
' 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:\Temp\CommandNames.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.
' 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:\temp\CommandNames.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.
- 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.
- Run EventWatcher.exe. On a Windows Vista install this is typically at:
C:\Users\Public\Documents\Autodesk\Inventor 2009\SDK\DeveloperTools\Tools\EventWatcher\bin\Release
On a Windows XP install it is typically at:
C:\Program Files\Autodesk\Inventor 2009\SDK\DeveloperTools\Tools\EventWatcher\bin\Release
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. - In EventWatcher, find the event UserInputEvents.OnActivateCommand and make sure the event has a check mark beside it.
- Run the whatever command in Inventor that you want to find the name for.
- 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.
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.
' 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.
' Get the command manager.
Dim oCommandMgr As CommandManager
Set oCommandMgr = ThisApplication.CommandManager
' Post the filename.
Call oCommandMgr.PostPrivateEvent(kFileNameEvent, _
"C:\Users\ekinsb\Documents\Inventor 2010\Showcasetest.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 return 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.
' 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:\Users\ekinsb\Documents\Inventor 2010\Showcasetest.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