Replacing Built-In Commands and Obtaining Their Ids

One main focus of the

Revit 2013 API
features
is better support for

add-in integration
.
This includes the possibility for an add-in to replace an existing Revit command with its own implementation.
Note that you cannot call an existing command, just replace it entirely.

Such a command replacement is demonstrated in a very simple form by the

DisableCommand SDK sample
,
which disables a command by replacing its implementation with a simple popup message.

A slightly more complex example is given by the

UIAPI SDK sample
,
which implements and installs an alternative command binding for the Design Model command to start up a new family freshly created from the conceptual mass template and display its 3D view.

These are the steps to replace a built-in Revit command:

  • Determine the RevitCommandId to replace by examining the journal file and searching for the name of the original command.
  • Create an AddInCommandBinding for this command id.
  • Provide an alternate implementation for the command binding.

List of all Revit Command Ids

To simplify the first step, Victor Chekalin aka Виктор Чекалин now presents a list of all Revit command ids,

In Victor’s own words:

I’m learning the ability to replace a Revit command with my own add-in implementation.
To replace a command, I must know CommandId of the command which I want to replace.
The help tells me I can find a CommandId in the journal file.
So the Revit SDK help doesn’t contains full list of CommandIds.
I have decided to correct this mistake and create that list.

I thought this information will be useful for you and other developers and send you the list of all command ids in both
text and
Excel
format.

Question: Wow!
How did you create this list?

Answer: It is my little secret how I’ve got it. Joke :-)

At first I thought the commands must be described somewhere.
I searched for the text ‘ID_EXPORT_IFC’ (the command name from the Dev Days Online – Revit 2013 API) in all files at the Revit Program folder.
So I found the UIFramework.dll file.
I opened this file in the text editor and saw XML data containing command descriptions.

Next steps were very easy.
I saved this part of the UIFramework.dll file to the XML file and read the XML data:


private IEnumerable<InternalCommandDef>
  ReadCommandsFromFile()
{
  using( var streamReader
    = File.OpenText( @"C:UsersChekalinVV"
      + "DocumentsRevitRevit2013SDK"
      + "RevitUICommands.xml" ) )
  {
    using( var reader = XmlReader.Create(
      streamReader ) )
    {
      while( reader.Read() )
      {
        if( reader.Name.Equals( "Command" ) )
        {
          InternalCommandDef commandDef
            = new InternalCommandDef();
 
          if( reader.MoveToAttribute( "Path" ) )
            commandDef.Path = reader.Value;
 
          if( reader.MoveToAttribute( "CommandId" ) )
            commandDef.CommandId = reader.Value;
 
          yield return commandDef;
        }
      }
    }
  }
}

Retrieve get CommandId info for each command and write it to the text file:


  using( var textFile = File.CreateText(
    @"C:UsersChekalinVVDocumentsRevit"
    + "Revit2013SDKRevitUICommands.txt" ) )
  {
    foreach( var command in commands )
    {
      RevitCommandId commandId = RevitCommandId
        .LookupCommandId( command.CommandId );
 
      if( commandId == null ) continue;
 
      command.CanHaveBinding
        = commandId.CanHaveBinding;
 
      command.Id = commandId.Id;
 
      textFile.WriteLine( "{0}t{1}t{2}t{3}",
          command.CommandId,
          command.Path,
          command.Id,
          command.CanHaveBinding );
 
      /* It is just a joke
 
      if( !commandId.HasBinding 
        && commandId.CanHaveBinding )
      {
        var commandBinding =
          App.ControlledApplication
            .CreateAddInCommandBinding(commandId);
 
        commandBinding.Executed += OnCommandExecute;
      }
      */
    }
  }
}

It is not necessary to get full CommandId properties, but I wanted to retrieve the CanHaveBinding property for all commands.
As I can see only two commands cannot have binding: Undo and Redo commands.
Although I try to bind ID_APP_EXIT command (just for test because it was the first command I found in the journal files).
It binds without any errors but doesn’t work.

Very many thanks to Victor for this interesting research and the useful comprehensive list!


Comments

20 responses to “Replacing Built-In Commands and Obtaining Their Ids”

  1. Hi Jeremy, hi Victor,
    after reading the command IDs, I assume they can be used with UI Automation.
    For example,
    ID_ANNOTATIONS_DIMENSION_ALIGNED
    can be found in the status bar text in this screen shot:
    http://thebuildingcoder.typepad.com/.a/6a00e553e1689788330147e270f039970b-popup
    So after knowing all command IDs, we could also invoke all commands:
    http://thebuildingcoder.typepad.com/blog/2011/01/ribbon-spying-and-ui-automation.html
    Cheers,
    Rudi

  2. Hi Jeremy,
    I really doubt if overwriting existing functions should be done at all.
    There are cases in which a plugin can affect the behaviour of the whole application, e.g. when using RegisterFailuresProcessor().
    In the worst case, it may be that one of your installed plugins suppresses all warnings and errors, avoiding you from performing the needed error solution even manually.
    When overwriting existing functions, it may be that the user doesn’t even know that he uses a replacement function, depending on the documentation you shipped with your plugin.
    Cheers,
    Rudolf

  3. Phillip Miller Avatar
    Phillip Miller

    You can also get a listing of all the Command_Ids from the keyboardshortcuts.xml file “)

  4. Hi, Rudolf.
    I haven’t seen this post before. Thanks for link. I think that information should useful for me.
    Regards, Victor.

  5. Hello, Phillip.
    Where can I get the keyboardshortcuts.xml file? I cann’t find it anywhere.

  6. Phillip Miller Avatar
    Phillip Miller

    Hi Victor.
    First you need to activate the keyboards shortcuts through the Revit UI by going to ribbon -> View -> User Interface -> keyboard shortcuts.
    Add a shortcut and that will create the shortcuts file. I hope that helps.

  7. Dear Rudi,
    Yes, very reasonable doubts indeed. Please take heed.
    Cheers, Jeremy.

  8. Dan Tartaglia Avatar
    Dan Tartaglia

    Hi Jeremy,
    Is invoking a command in this manner a recommended approach?
    Thanks,
    Dan

  9. Dear Dan,
    There is currently no recommended approach to invoke a command. The Revit API does not support it at all. All you can do at the moment is replace a built-in Revit command with your own implementation. Everything else is unsupported and not recommended.
    Cheers, Jeremy.

  10. sangsen Avatar
    sangsen

    Hi..Jeremy..
    I am creating commandBinding() for revit “CreateSimilar” functionality. But I am not able to get orginal behaviour of “Create Similar” after removing Executed event from the document. How can i acheive this?
    Thanks

  11. You realize that the Excel sheet also exposes all internal Debugging commands? That is actually very handy.

  12. Dear Martin,
    Thank you for pointing this out. Nope, I did not realise that.
    Why do you find them handy, please? What do you use them for?
    Thank you!
    Cheers, Jeremy.

  13. Dear Sangsen,
    Have you tried using UIApplication.RemoveAddInCommandBinding?
    Cheers, Jeremy.

  14. On a semi-related note, I’m trying to identify the commands associated with Detail Lines for creating custom keyboard shortcuts. Modifying the commands for Contextual Tabs>Draw works for Filled Regions, Floors, etc. but does not seem to work for Detail Lines. Any idea where else to look?
    Is there any way to get the command id associated with a particular button?

  15. Dear Mark,
    I would have expected them to be in there.
    If not, have you looked in the journal file?
    Cheers, Jeremy.

  16. Michael Avatar
    Michael

    Doesn’t seem to have “Edit Family” either which I really need.

  17. Dear Michael,
    I guess they thought that you can do more with the EditFamily API method, and using OpenAndActivateDocument to navigate.
    Or there were other internal reasons for not exposing such a complicated command :-)
    Cheers, Jeremy.

  18. What if you were looking to have a warning dialog and then proceed with the originally requested command.
    So you could use the commandBinding then run a eventhandler to show the dialog, could you then have the original command run after the user clicks OK on the warning box?
    or is that a different process than commandbinding? Is there a process to catch when standard Revit commands are run and do things alongside the command?

  19. found it:
    AddInCommandBinding.BeforeExecuted Event

  20. Cheeky question, but is there an updated list of internal commands for 2015? I am not sure what assembly reference I need for the InternalCommandDef so I haven’t managed to get it working to try to get the data myself.

Leave a Reply to DrewCancel reply

Discover more from Autodesk Developer Blog

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

Continue reading