Saikat Bhattacharya

03/06/2013

I have had couple of emails in recent past with different third party developers providing me with their Revit add-in samples, where they are stuck because of the following System.TypeLoadException.

As mentioned here, the reason for this exception typically is that CLR did not find the assembly, or the type within the assembly or could not load the type. This in most cases that I have seen with Revit add-ins seems to commonly due to a mismatch between the .NET framework and the Revit version being used to develop the add-in. There are also couple of discussions on this topic in the Revit API discussion forum.

In the recent case, I had spent quite sometime confirming that the correct for the .NET framework was being targeted for in the VS project, the version of the Revit API references, and other settings and even double checked that entries in the .addin manifest file – all of which seemed perfect. Next, I started reading through the VB.NET code and immediately saw Namespace was provided in the code as well as in the Root Namespace field in the VB.NET project settings. Once I removed the Namespace entry from the code, the Add-in loaded up just fine in Revit. This would be a typical case whenever we end up converting C# code to VB.NET. Something to watch out for!

03/05/2013

We have so far received atleast a couple of queries stating something like -

While using Visual Studio 2010 and having referenced Revit API in my project, I also added some web reference to the project. I notice that the build process fails and the error mentioned below is thrown:

Error 1 An attempt was made to load an assembly with an incorrect format: C:\Program Files\Autodesk\Revit Structure 2013\Program\RevitAPI.dll.

SGEN

But when I try to debug, the project is working fine without any problem. How can I fix this?

The reported issue with the build error seems to be a generic issue with WebServices consumption in a .NET application with the project configured for release mode.

I found out (and tested) that under Build tab in Visual Studio project properties, you can set the Generate Serialization Assembly setting to Off (from Auto). This will disable the generation of the projectName.XMLSerializers.dll and this assembly will be generated dynamically at runtime (instead of compile time).

And this change of setting resolves the build error you have reported.

To read up more on this setting, you can find relevant information on MSDN – one such link is:

02/20/2013

Whenever there is a requirement to access any specific parameter value of an element, like the Material value of a Panel, in this case, Revit LookUp tool often provides the exact approach required to access the desired information.

So getting back to this specific case, we can create an instance of the StoreFront curtain wall type and select a panel and drill in through the instance (and/or type) parameters to see which one contains the Materials based information (this can be also figured out using UI). In this case, the Material information of a standard curtain wall panel is stored in the PanelType. And based on this information as obtained from the LookUp tool, the following code should help extract (and if required, set) the Curtain Wall panel.

using System;

using System.Collections.Generic;

using System.Text;

using System.Linq;

using Autodesk.Revit.Attributes;

using Autodesk.Revit.DB;

using Autodesk.Revit.UI;

namespace Revit.SDK.Samples.HelloRevit.CS

{

[Transaction(TransactionMode.Manual)]

publicclassCommand : IExternalCommand

{

publicResult Execute(ExternalCommandData commandData,

refstring message,

ElementSet elements)

{

UIApplication uiApp = commandData.Application;

foreach (Element ele in

uiApp.ActiveUIDocument.Selection.Elements)

{

Panel panel = ele asPanel;

PanelType panelType =

doc.GetElement(panel.GetTypeId()) asPanelType;

if (null != panelType)

{

ElementId id =

panelType.get_Parameter(

BuiltInParameter.MATERIAL_ID_PARAM).AsElementId();

if (id != null)

{

Material mat = doc.GetElement(id) asMaterial;

TaskDialog.Show("Material Name", mat.Name);

}

}

}

returnResult.Succeeded;

}

}

}

If you have a custom curtain wall, the approach will be different and you can get an idea of how to access the required parameter values using the Revit LookUp tool again.

02/18/2013

In the recent past, we had received some queries around refreshing the sections directly using the API (without having to use SendCommand).

There isn’t any direct API which allows API users to the refresh on the sections/elevations. Sending the command using SendCommand would be one workaround for some API users. But if SendCommand is not an option (as in this case), the ACA 2013 .NET API provides a method called GenerateSection which can help generate 2D sections programmatically. The method signature is included below - Autodesk.Aec.ApplicationServices.Utility.SectionUtilities.GenerateSection(Autodesk.AutoCAD.DatabaseServices.ObjectId, Autodesk.AutoCAD.Runtime.RXClass, string, string, bool, string)

This API might help re-create sections and this might be closest to what we can do as work-around for now.

02/15/2013

I am using the following code to associate/disassociate a family parameter from/to an element parameter. doc.FamilyManager.AssociateElementParameterToFamilyParameter(ep, fp)

I can associate fine. However, there are no instructions on how to disassociate. Can you let me know how to disassociate a Family parameter from an Element parameter.

Resolution:

As per the Revit API chm file, the same AssociateElementParameterToFamilyParameter() method can help disassociate a element parameter from an existing family parameter. The only change would be that the value of the family parameter would be null (or Nothing in VB).

So to test this, calling the AssociateElementParameterToFamilyParameter() method once, it creates a column family and also associated the element parameter with family parameter, as shown below:

Next, if we add another line of code to call the same method and instead pass null as family parameter, the following dialog confirms that the disassociation works as expected:

02/14/2013

In the Auto_08.vbs sample in Navisworks Manage 2012 (or the AutoPublishScriptExample sample in Navisworks 2013), which can be located from the Navisworks install folder location (typically under Navisworks 2012\api\COM\examples location) - the VB Script file takes an input file and creates an expiring output file using the Publish API.

If a system has multiple versions of Navisworks installed and we want to determine which version of roamer.exe was used to do the publish, we can add the following simple lines of code and extract the required information:

ver=roamer.state.fileversion(arg_out) MsgBox(ver)

All that is being done here is to check the file version of the output file and determine which flavor and version of NW was used to generate the NWD file. Please do remember to declare the variable ver using the Dim statement, at the beginning of the sample.

02/07/2013

A question that has often come up repeatedly is on retrieving wall paint materials:

There is a Paint tool in Revit that a material can be 'painted' on a surface of a wall. How can we access the paint material information via the API?

With the Revit API, we have the ability to get the regions of each face of solids (walls in this case) and each region will provide material information as well.

Following is a note from the Revit 2012 API chm file on this topic, that provides further details on how to use the API to access the Paint material :

Face.HasRegions & Face.GetRegions()

This property and method provide information about the faces created by the Split Face command. HasRegions returns a boolean indicating if the face has any Split Face regions. GetRegions returns a list of faces. As the material of these faces can be independently modified through the UI with the Paint tool, the material of each face can be found from its MaterialElementId property.

02/06/2013

Is it possible to update saved viewpoints in Navisworks through the .NET API after they have been created. For example, if we want to update views after hiding some objects.

Navisworks .NET API includes a method called DocumentSavedViewpoints.ReplaceFromCurrentView(). This method can help replace the SavedViewpoint that is being passed on to this method with an updated copy. Viewpoint, Redlines and visibility are updated to those in the current View

02/05/2013

Similar questions like that of the title of this post, has come up a couple of times in the recent past. This topic has been covered in this blog-post too – though from a slightly different perspective.

As mentioned in this blog-post, the key to finding out if a Family Instance requires a host or not is to find out the Host parameter of the Family itself. This blog-post contains a screenshot of a Outlet-Duplex family instance (which is wall based) and shows how Revit LookUp tool can be used to confirm that the value of the HOST parameter as 1 (which confirms that the Family is wall-based). Once a given family that needs to be determined, is loaded into a Revit model, there is no need to create an instance of the family and then edit it and then access the HOST parameter – the loaded Family itself will provide access to the value of this parameter directly to help determine if the family needs a host and if yes, of which type.

02/01/2013

In response to the comment on this blog-post where there was a query on how to hide sections in all the plan views using the API, I wrote this short code snippet to illustrate the workflow:

As a first step, we need to filter out the plan views. Then on each plan view, we filter the sections created on them. This is done by checking the elements of category OST_Viewers and their Type Name to be Building Section. With this list of Ids of Sections on a given plan view, we can simply call HideElements() to hide the sections on that plan view.