The never-ending stream of Revit API topics continues.
Today, let's look at:
- Unrestricted VendorId.
- Retrieving DWFx links.
- Batch processing Revit documents.
- Future-proofing The Building Coder samples.
- Recent Revit API AEC DevBlog posts:
In the past, we recommended using an Autodesk registered developer symbol or RDS as your vendor id, stored in the add-in manifest
(starting from the Revit 2012
extensible storage and
Autodesk registered developer symbols are very limited, though, consisting of only four characters from a restricted set, [A-Z], [0-9], minus '-' and underscore '_'.
The Autodesk registered developer symbol usage is now deprecated, so this restriction has been lifted for the Revit VendorId specification.
- VendorId – A unique vendor identifier that may be used by some operations in Revit (such as identification of extensible storage). This must be unique, and thus we recommend using reversed version of your domain name, for example, com.autodesk or uk.co.autodesk.
Accordingly, I should update my Visual Studio Revit add-in wizard to use
com.typepad.thebuildingcoder instead of the current RDS
TBC_... to be done asap.
Retrieving DWFx Links
Let's look at how to retrieve DWFx links from the current Revit project.
This question was raised and solved by Daniel in the Revit API discussion forum thread on getting all linked DWFx files in the Revit document:
Question: I'm trying to list all links in a document using filtered element collectors.
I get the RVT links (Revit and IFC) through the built-in category; DWG links also work fine using the
I thought that DWFx and point clouds also should be listed under this filter?
It seems not, though. I can't get them through that filter, and I can't see any other type to use.
Answer: While working on creating a minimal reproducible sample, I found the error.
It's kind of simple. DWFx files are not linked, even though they appear to be so.
When I changed from:
var dwgLinks = fecDwgLinks .OfClass(typeof(ImportInstance)) .ToElements() .Cast<ImportInstance>() .Where(f=> f.IsLinked);
var dwgLinks = fecDwgLinks .OfClass(typeof(ImportInstance)) .ToElements() .Cast<ImportInstance>();
Things worked fine.
This code returns other links as well, but that is how I want it.
I am creating a tool that lists all the links.
When I use the collected elements, I use the category name, which contains the filename extension, to group the different types of links:
var namearray = importlink.Category.Name.Split('.'); var name = namearray.FirstOrDefault(); var extension = string.Empty; if (namearray.LastOrDefault() != null) extension = namearray.Last();
I have created an Enum to group a list on:
GroupingEnum lType = GroupingEnum.Unknown; if (extension.ToLower().Contains("dwg")) lType = GroupingEnum.Dwg; else if (extension.ToLower().Contains("dwf")) lType = GroupingEnum.Dwf;
This is used to group a list so that it is easy to choose the wanted elements.
Batch Processing Revit Documents
Question: I'm looking at building a Revit service that processes Revit families on demand and extracts Revit family information.
Do you know of anyone who has done this before?
I have been reading the discussion on driving Revit through a WCF service.
I'm stuck on the problem that I will run into Revit errors that can't be handled through the API or Revit will eventually crash.
I will have to kill the Revit process, skip the family and start another Revit process.
How will I detect that Revit has stopped working?
Here is my proposed architecture:
- Install Revit on a server.
- Build a Revit plugin that extracts Revit family information, also the plugin subscribe to the Idling event and checks a WCF queue.
- Build some queue managing software on the server that receives the Revit family and add it to the WCF queue.
- Revit Idling event processes the families in the queue and adds the results to a database.
Easy so far.
But how do I catch in the queue managing software if Revit crashes or a warning dialogue pops up and stops Revit?
I could use time if Revit takes more than 2 minutes to process a family than it is not responding end the Revit process (crash it), skip this family and start up another Revit session.
How would you detect if Revit is not responding?
Answer: I think the blog post you point to is a good starting point.
I have summarised several other related discussions in The Building Coder topic group on Idling and external events for modeless access and driving Revit from outside.
By the way, I recommend never using the Idling event, if it can possibly be avoided. External events are more flexible and do not block the entire system, like the Idling event sometimes does.
Otherwise, your architecture sounds absolutely fine to me.
Yes, you should assume that Revit will stop working after a while when driven in this manner.
That is to be expected, since it is implemented to be driven in a completely different manner, interactively, by a human user.
How to check when it stops working?
Probably the best approach is indeed to implement a timer and see how long it takes to complete the current request.
Once the timeout is exceeded, assume it died, kill it properly, and restart at that point.
This is a standard approach for driving lengthy complex batch processes.
Future-Proofing The Building Coder Samples
I continued in my perpetual struggle to future-proof The Building Coder samples by eliminating all deprecated API usage.
The result of my latest effort is release 2016.0.120.9, which compiles once again with zero warnings.