Addin File, Learning Python and IFC.js

Today, we look at the add-in manifest, learning Python and Dynamo, the status of the Revit Python shell and a useful stand-alone IFC viewer:

Personalised Add-In Manifest

Andrea Tassera of Woods Bagot raised an interesting question in the Revit API discussion forum thread on using relative paths (%appdata%) in .addin file:

Question: Is it possible to use a relative path, such as %appdata% in the Assembly section of the addin file?

I am developing this plugin that will be deployed to other people in the company, and the DLLs will live somewhere in C:\Users\\AppData\Roaming\NameOfFolder... so writing the explicit path with the user name is not a real option. Normally, in Windows, you would use %appdata%, but it doesn't seem to be working in the .addin.

Is there a way?

This is what I tried but isn't working:

<?xml version="1.0" encoding="utf-8"?>
<RevitAddIns>
 <AddIn Type="Application">
       <Name>Wb.ModelEstablishment.Revit</Name>
       <FullClassName>Wb.ModelEstablishment.Revit.Ribbon</FullClassName>
       <Text>Wb.ModelEstablishment.Revit</Text>
       <Description>Model Establishment</Description>
       <VisibilityMode>AlwaysVisible</VisibilityMode>
       <Assembly>%appdata%\folder\subfolder\Wb.ModelEstablishment.Revit.dll</Assembly>
       <AddInId>d06838e1-44e3-4c05-b9f1-f79ca101075c</AddInId>
    <VendorId>WB</VendorId>
    <VendorDescription>Woods Bagot</VendorDescription>
 </AddIn>
</RevitAddIns>

But, if I use the explicit path:

  <Assembly>C:\Users\sydata\AppData\Roaming\folder\subfolder\Wb.ModelEstablishment.Revit.dll</Assembly>

... it works fine.

Answer: Yes, it is definitely possible to use relative paths in the add-in manifest.

However, %appdata% is not a relative path.

That is a variable in an MS-DOS or Windows batch file, or possibly nowadays in a PowerShell script or something suchlike.

Revit add-in manifest files do not support variables, neither MS-DOS nor Windows nor Unix nor any other flavour.

You can read about what is and is not supported in manifest files in the Revit online help section on add-in registration.

Look there for 'In a non-user-specific location in "application data"'.

Response: I have read the page you sent, but the whole 'user-specific' or 'non-user specific "application data"' talks about where to save the .addin file, not how to point to dlls placed in the %appdata% folder through the Assembly XML tag inside the .addin file.

The .addin file can be in the user folder:

That's not a problem. The problem is that the Assembly tag needs to point to a roaming folder:

I don't know how to achieve that without using the absolute path.

I can't write one specific addin file for every user in the office.

Does it make sense?

Answer: Yes, absolutely, it makes perfect sense.

As said, the %appdata% variable that you are referring to is a Windows specific variable that is not understood or supported by the add-in manifest file.

One simple option I see for you is to (automatically) generate a user-specific add-in manifest for each user and place each one in the appropriate user-specific location.

Another possible approach would be to place one single add-in manifest file for all users into the system-wide global location, and then use other run-time criteria to determine whether or not to make individual add-in functionality and components available to each user on a case-by-case basis, e.g., using the Revit API AvailabilityClassName.

Oh, and another thing, much simpler:

I almost never use the add-in assembly DLL path at all.

I just place the add-in assembly DLL in the same location as the add-in manifest *.addin file, and then it is found without specifying any path at all.

If you are already placing the add-in manifest file in the user-specific location, why don't you just put the DLL in the same place?

Response: Thanks for clarifying. I get what you mean now!

Unfortunately, the DLLs are in the %appdata% folder because they come through pyRevit, and the repository gets pulled under:

Usually, pyRevit doesn't need addin files, but this is a linkbutton, because I need things to happen at application level (like registering a dockable panel), so it needs to have an addin file to load the DLLs when the Revit application is loading. It's a bit more complex than usual.

We could maybe write a PowerShell script that moves those DLLs somewhere else, but it seems a bit convoluted.

Creating an automatic generator of the addin sounds interesting though. From the docs you posted, I don't understand where that code would live though. It says that "It is intended for use from product installers and scripts". Does that mean something like a PowerShell script?

Answer: You mean the RevitAddInUtility.dll?

The answer is Yes, cf. The Building Coder article on RevitAddInUtility.

Addin Manifest Using a Relative Path

Jason Masters added a more direct and down-to-earth solution:

I believe the answer you're looking for is to just use the relative path modifier for moving up a folder level ..\. There's no need to run a script at install just to get to a user's appdata folder.

For instance, if I put my add-in DLLs under a different roaming folder like so:

Add-in manifest relative path

Then, to access those DLL files from my add-in, I can simply use ..\ to navigate up to my roaming folder; in this case, I'm navigating up 4 levels:

Add-in manifest relative path

When I launch Revit, you'll see that it's parsed the path correctly and will load the add-in:

Add-in manifest relative path
Add-in manifest relative path

Also, %appdata% is the specific notation that cmd.exe and other Windows utilities use to refer to the appdata environment variable, but environment variables are in no way Windows specific and are commonly used on all operating systems. Revit really should support the use of environment variables in these addin files.

Learning Python and Dynamo

Next, let's look at the recurring question of beginners materials for Revit API using Python from the Revit API discussion forum thread on a best book for Python for Revit and Dynamo:

Question: I'm starting to learn Python (and Dynamo) and encounter the problem of how to learn to use it for my actual needs in Revit. I got a whole bunch of Python books from the library. One problem is the books are either focused on examples to make simple videogames, or are way to advanced (and also not based on examples one would use in Revit). I have to admit, some children-oriented books were easier to understand :-)

There is a Dynamo for Revit: Python Scripting book, but that is not currently available. Are there actually books or sources that would teach Python on examples one would use for Revit/Dynamo? I'm learning best on an example I actually use.

I also found there is a Revit Python Shell (RPS) on GitHub, but none for Revit 2021. Is there something similar? I saw some videos of how one can do some useful things in Revit.

Answer: The best and most up to date sources tend to be online these days. The second source is for RPS as you mentioned but would probably be my starting point for something specific to Revit.

People seem really passionate about Python, don't they. I'm no expert on this so maybe people have good book suggestions, but I prefer online for all aspects of learning generally.

Answer: The “book” you refer to is actually a video tutorial by Jeremy Graham on LinkedIn. Probably one of the best ways to get started.

Answer: To start with Python and Dynamo, I think this Autodesk University Class on Untangling Python: A Crash Course on Dynamo‘s Python Node by Gui Talarico is a great resource.

If you have some basis but you don´t know how to move on, a good way to learn Python applying to Dynamo is to download 3rd party packages (Archilab, Clockwork, Lunchbox, Rhythm, Bimorph, Spring nodes, etc.) and read the code that the nodes contain. You will see really good implementations and good practices. You will be able to see how others think about problems and write the solutions.

Have a good understanding of Object-oriented programming will help you on this and is a key aspect to understand how to use the Revit API with Python.

About the resources, as is mentioned in the previous posts, I would take a look on LinkedIn learning and also at thinkparametric.com. There are good courses there.

Good luck!

Answer: RevitPythonShell for Revit 2020 works just fine in Revit 2021 as well, cf. issue #106.

Response: Thanks all. I'll digest what was offered.

So far the Automate the Boring Stuff with Python book seems to be the best I could find in the library. So, I guess I will look more and start to dig deeper when I create some dynamo programs.

I won't be able to install the Python shell in Revit. Since that is free, they don't really provide the security certificates our IT requires to allow installation. My hope is Revit will include it at some point (since Autodesk is already approved by IT). Until then I have to limit myself to the Python in dynamo nodes.

Answer: The vast majority API support examples are in C# but Python is sexy.

Answer: If you have Revit installed, Python is included: it is supported by the built-in Revit macro IDE (integrated development environment).

Response: You mean the macro manager?

I haven't done anything with that yet. So, if that does what the Python shell does, I use what I already have.

Macro manager for Python

Answer: The macro manager does not quite do the same thing as RPS.

RPS provides a REPL, read-evaluate-print loop.

That enables you to interactively program something, line by line, and execute each line as you type it.

The macro environment enables you to create and execute macros. That means that you have to complete an entire macro and compile it before it can be executed.

In any case, the simplest way forward for you would be to use what you have and work through a Revit macro tutorial first of all.

Response: Thanks for the advice. I'll look into that.

I have a (growing) list of features or solutions I need in Revit and will try to work on solutions. Some will require some general Revit trickery, some dynamo, some macros etc. that way I will learn to sue the tools inc. Python.

Answer: Oh yes, we mentioned another book just two months ago, Más Allá de Dynamo – Beyond Dynamo, a Spanish-Language book by Kevin Himmelreich and the first Python manual focused on Dynamo and the Revit API. Even though it is in Spanish, you can understand most. It includes a bunch of examples and pretty much everything about the Revit API is covered in Python.

Jacob's Dynamo Learning Resources

My colleague Jacob Small reacted to the above and adds:

Just saw your latest blog post, and thought I'd share a few more Dynamo and Dynamo Python educational resources (PDF), in case they help. Feel free to share around as needed... Thanks as always for the great content on the blog – they're on my 'always read' list as, even if it's not a need today, they usually come up eventually.   :-)

Many thanks to Jacob for this useful collection!

Take Dynamo Further Using Python

Wayne Patrick @waynepdalton Dalton adds:

Hello Jeremy, not sure if this was mentioned in the section on Dynamo and Python (don't think it was?)

@Oliver_E_Green put together a great resource for @DynamoBIM and #Python... thought it might be helpful to flag it for those wanting to learn:

Take Dynamo Further – using Python will take your Dynamo definitions to the next level

Thank you, Wayne, for the helpful pointer!

Quo Vadis, RevitPythonShell?

I just happened to hear that RevitPythonShell is no longer actively supported by its creator and hitherto maintainer Daren Thomas, cf. our conversation on issue #111.

Says Daren:

As of next month, I will not have access to Revit anymore, and the project will need a new maintainer.

I am very sorry to hear that, and ever so grateful to Daren for creating RPS in the first place and maintaining it for so long.

RevitPythonShell was the first interactive REPL for Revit, followed by the sexier but less long-lived RevitRubyShell.

In case of interest, please vote for pyRevit issue #1161 – pyRevit Python Shell?

IFC.js

From Python, let's turn to JavaScript and note the very interesting project IFC.js, described by Antonio González Viegas on aechive.net:

an open source IFC web viewer. It is fully built on JavaScript and Three.js, and everything is done client-side... anyone with a browser can navigate IFC files (geometry and information) without depending on native applications... advantages...