In this post I will go over some of the most useful things that you need to learn to be able to successfully create Revit plug-ins and some good coding practices (I hope they are good because I am not actually a computer scientist – just a lowly architect):
- using statements for external libraries
- IExternalCommand implementation
- Exception handling
- Pseudo code and commenting
- Addin files
We ended last post upon successfully adding RevitAPI and RevitAPIUI dlls to our project. Now let’s tell our plug-in that we are going to use them:
This three lines will allow us to use Classes and Methods defined in the two external libraries. They will basically give us access to everything that we will need from the Revit API. Now that we have them referenced in let’s look at IExternalCommand implementation.
- Hover over the IExternalCommand. Little yellow bulb will appear, click on the down arrow next to it to reveal a contextual menu. It should give us two options. Click on Implement interface.
This will “implement” the interface called IExternalCommand which is what Revit uses to recognize plug-ins. Our code should look like this after I deleted some redundant stuff that get’s put in automatically:
Now, really quickly I will do something that I call adding “pseudo code”. This is pretty good practice when coding. It’s basically a road map for what we want to do in our code and what order we want to achieve this. You probably also noticed that Execute has been underlined in red. That means that our class is missing something. In this case the message bubble states that “not all code paths return a value”. It means that we are missing “return” statements. For IExternalCommand to work properly it has to return a Result.Failed, Result.Canceled or Result.Succeeded. You don’t always need all three of them, but in case of our plug-in we will actually use all three. Let’s also add those in:
What you see above is called “pseudo code”. It’s just me adding text notes to my code to let myself know what I think I need to do in my code to successfully create my plug-in. Now that we have our road map, let’s create a little framework that we will be working within. What I mean by that is adding “try” statements to take care of possible errors (it’s always a good idea to enclose your code in try-catch), as well as return results so that our “Execute” method stops barking at us with that ugly red underline.
Please pay attention to couple of things that we did here:
- This is how you “catch” a very specific error. Since I know that this error is actually very common, I will list it out here. This error will happen if user hits ESC button during selection process. We will talk about this a little more later so stay tuned.
- This is how you “catch” unexpected errors. There might be things that happen, that you didn’t anticipate in your code, so this statement will catch them and then return them as “message”.
This part was pretty straight forward. There is only one more little thing that Revit requires for all its External Commands – Transaction Attributes. Transaction Attribute is telling Revit what method to use to manage Transactions for a given plug-in. Our options are either Automatic in which case Revit will try to automatically create a Transaction for us when it deems it necessary. Another option is Manual, in which case we will have to make sure to start a new transaction in our code for every process that modifies Revit’s Database. I personally prefer the Manual mode of transactions as it makes it clearer when we are making changes to Revit document. To define this attribute we need a single line of code like that:
So there it is. We have the structure of our plug-in in place. We defined the sequence of how we will create our plug-in using pseudo code, we implemented IExternalCommand with Transaction Attribute and prepared ourselves for potential errors and how to handle them. Now, we just need to add a *.addin file to our assembly and we can build our plug-in. For those of you not familiar with *.addin, its a file that tells Revit to load our plug-in DLL file when Revit starts. Addin and Dll files will always go together. Let’s do that really quickly.
- Right Click on the assembly name in Solution Explorer.
- Navigate to Add
- Click on New Item…
This will produce another window that we should be familiar with already:
- Select Text File from the list.
- Insert a name for the file with .addin extension.
- Click Add.
Now we just need to add a few things to our addin file that will tell Revit what to look for.
Next, we have to change the Build Action for our addin file, so that it actually get’s created with our DLL file (remember we will need both of them).
- Select our addin in Solution Explorer.
- Change its Build Action to Content and change its Copy to Output Directory property to Copy if newer.
Now if you navigate to Build and click on Build Solution:
This will create the two files that we need in the following location:
- This is the location that if you remember we specified our new Visual Studio project to be located.
- This is the location that Visual Studio creates for us. Every time we hit “Build” it will replace files in this location unless otherwise specified.
- These are our files that we need for the next step.
Now that we have our DLL and Addin files, we just need to add them to the Revit Addins folder so that Revit can load them up next time it starts. Just copy/paste these two files to the following location:
Keep in mind to change the “ksobon” to your own user name.
Now, if you fire up Revit, you should be able to find this on your Add-ins tab:
You can go ahead and click on it, but nothing will happen since our code, doesn’t yet do anything other then return Result.Succeeded. :-)
In the next part of this tutorial we will talk about ISelectionFilter and how to ask user to select things in Revit so that our plug-in can process them.