I want to subscribe to every single Command in Revit.
I've read this: Replacing Built-In Commands and Obtaining Their Ids and grabbed the list of Ids provided but it's got me wondering:
What if there are new commands that aren't on this list? How do I capture them? Is there an enum I can iterate over yet?
The Command Ids are an integer, right? So here's a wonderfully terrible idea: I could iterate through all the possible Id values and just catch{} all the exceptions. It'd guarantee that I didn't miss any and it'd be 100% future proof (unless they changed how Ids are stored). It'd also take a crazy amount of time.
But it'd work!
But it's stupid and brute force.
There's got to be a better way, right?
Solved! Go to Solution.
Solved by matthew_taylor. Go to Solution.
Dear Thomas,
The most reliable way to determine a command id is to run the command and then look up the resulting entry afterwards in the journal file:
Cheers,
Jeremy
I saw that. I've also found a nice article about extracting the information from a journal file using a pascal script: Visualizing Revit Journals
Problem with that solution is I'd have to click on every button in Revit to get every command which is obviously impractical and as soon as a new button is added, my list falls out of date.
Hi @Anonymous,
It's unsupported, but check out my comment in this post:
Extend that with this code and you should be away:
For Each ribbonItem In panel.Source.Items Dim id As String = ribbonItem.Id ....
Some filtering of ribbon item types may be required.
Hang on! There is a list of RevitCommands in the API! It's the RevitCommands.Names static variable!
This works fine:
foreach (string name in RevitCommands.Names) { try { var binding = app.CreateAddInCommandBinding(RevitCommandId.LookupCommandId(name)); binding.BeforeExecuted += Command_BeforeExecuted; } catch { continue; } }
Wait, no, I'm a moron. I wrote that RevitCommands class a few weeks ago and then forgot about it. It's just a static list of all the names provided by the post linked in my original question.
I was looking for the same thing and found that exporting the keyboard shortcuts xml file gives you a list of all command names and ids.
Wow. That sounds very useful. Thank you for sharing this important observation. Does the XML file really list all commands, even if no shortcut has been assigned to them?
I know this thread is years old, but worth a shot! I'm trying to find the command associated with when you click the View template button on a view:
In the xml of keyboard shortcuts, there are 3 commands associated with view templates. However, none of them trigger when clicking this button
I tried looking in the journal file and found this line:
It looks like clicking that button calls multiple functions maybe?
I have been able to subscribe to the "DialogBoxShowing" Event, however, that event doesn't give me the options I am looking for. I would like to be able to intercept the command BEFORE the dialog box pops up, and to do that, I need to know the command ID. Any ideas?
The button you are interested in supports editing of an individual Revit BIM Element property.
Many of these properties are stored in parameter values, so the editing is simple, just modifying a single atomic object.
Some properties are more complex, like the Location of an element; it can be either a LocationPoint or a LocationCurve, both of which can be represented in the Revit API, or something else, that has no API representation and thus cannot be accessed at all in the API.
Other properties are more complex still. They come equipped their own internal custom editor and often completely lack any kind of API presence whatsoever.
The button you are interested in seems to belong to the latter category. Clicking it launches an internal custom editor to which you have no access whatsoever, editing internal properties are are probably equally inaccessible.
So, you can completely forget this approach.
If you share what you are trying to achieve, there may be some other way. However, your question has nothing to do with the topic discussed in this thread, so you might as well find a more suitable thread for it or start a new one.
Basically, what I’m trying to achieve is to block certain users from being able to edit the view templates. That’s why I was hoping to be able to intercept the command of the button , but based on what you said, this button doesn’t behave the same way as a typical Revit ribbon button. So yea it is either not possible or requires a very different method than what this thread mentions. I’ll keep digging
Aha. Well, that can certainly be achieved. One way may be to use a dynamic updater:
Determine the exact nature of the things you do not want the user to modify. Implement a trigger that identifies those. If the DMU is triggered, the protected elements have been modified. In that case, the DMU can cancel the action and issue a warning.
There may be other approaches as well... almost certainly, and maybe better. I would suggest searching this frorum for the term "prevent" and similar:
Please let us know how you end up solving this. Thank you!
thanks @jeremy_tammik for pointing me to Iupdaters. I think I'm 90% of the way there. I have it working so that it alerts when a change is made to the view template, however, I don't know how to make it cancel the action as you describe? Here is the code for my updater class (it's in python, but I can understand C# too if you have a C# example".
class ViewTemplateProtectionUpdater(IUpdater):
def __init__(self, application):
self._addinId = application.ActiveAddInId
self._updaterId = UpdaterId(self._addinId, Guid.NewGuid())
self._application = application
def Execute(self, data):
doc = data.GetDocument()
for id in data.GetModifiedElementIds():
el = doc.GetElement(id)
if isinstance(el, DB.View) and el.IsTemplate:
UI.TaskDialog.Show("View Template Modification", "Modifications to view templates are not allowed.")
def GetUpdaterId(self):
return self._updaterId
def GetUpdaterName(self):
return "View Template Protection Updater"
def GetAdditionalInformation(self):
return "Blocks unauthorized modifications to view templates."
def GetChangePriority(self):
return ChangePriority.Views
def Register(self):
if not UpdaterRegistry.IsUpdaterRegistered(self._updaterId):
UpdaterRegistry.RegisterUpdater(self, True)
filter = DB.ElementCategoryFilter(DB.BuiltInCategory.OST_Views)
UpdaterRegistry.AddTrigger(self._updaterId, filter, Element.GetChangeTypeAny())
print("Updater registered.")
def Unregister(self):
if UpdaterRegistry.IsUpdaterRegistered(self._updaterId, self._addinId):
UpdaterRegistry.UnregisterUpdater(self._updaterId, self._addinId)
print("Updater unregistered.")
Can't find what you're looking for? Ask the community or share your knowledge.