RevitLookup 2020含源码addin深度解析:编译、加载与定制实战
2026/9/7 8:19:57 网站建设 项目流程

简介:面向Revit二次开发者的RevitLookup 2020工具包,内含完整C#源码、可部署的addin插件清单及配套资源,用于快速查看Revit图元、族实例、几何数据与内部参数,是调试Revit API和开发插件时的常用辅助工具。压缩包共161个文件,涵盖78个cs源文件、13个resx资源定义、17个bmp位图、4个ico图标、3个dll程序集及2个addin清单;cs为项目主体,resx保存界面文本与资源映射,bmp/ico构成工具栏和树形图标,dll支持扩展功能,整体仅1.05MB,结构紧凑。资源已在Revit 2020环境亲测可用,若因本机SDK引用路径不一致导致加载失败,可用Visual Studio打开解决方案,修正引用后重新编译dll。目前已有1650人学习下载,对于想直接集成该插件或二次修改界面的开发者,含源码版本比单独二进制更利于定制、追踪问题,也可作为学习Revit API遍历对象模型的入门范本。总体而言,这份资源既是一个开箱即用的调试工具,也是一份值得研读的Revit API示例工程。 做Revit二次开发的兄弟,应该都认识这个名字:RevitLookup。这个工具说白了就是Revit API调试界的“照妖镜”,不管你是新手第一次接触Revit API,还是老手写了几年插件,只要你能选中一个元素,它就能把这个元素在Revit内部的数据结构、参数、几何信息、扩展数据全部摊开给你看。而标题里提到的“含源码和addin”,意味着你拿到的不是打包好的黑盒,而是完全可以自己编译、修改、定制的一套完整工程。

这篇东西我主要围绕RevitLookup 2020这个版本来写,谈谈源码结构、addin加载原理、编译过程中容易踩的坑,以及我在实际项目里怎么拿它快速定位API问题。适合刚准备入坑Revit二次开发的人,也适合想深度理解Revit数据模型的同学参考。如果你是拿插件当黑盒点按钮用的那种,那这篇文章同样有用,至少你能搞清楚它为什么能显示出那么多信息。

1. 项目工程拆解:RevitLookup 2020到底解决了什么问题

1.1 为什么每个Revit开发者都会装它

我见过太多人写Revit插件时,卡在同一个问题:我知道有某个参数,但不知道它的BuiltInParameter枚举名叫什么;我知道构件有几何,但不知道它的Solid内部到底有哪几个Face、每条Edge的拓扑关系是什么;我想读取共享参数,但参数GUID和StorageType总对不上。

这种问题,你去翻RevitAPI.chm文档效率太低,用Visual Studio的调试器一点点看内存又太费劲。RevitLookup就是专门解决这个问题的:它在Revit进程内运行,直接拿到当前文档的UIApplication和UIDocument对象,然后把一个Element、一个Face、一条Edge甚至一个Parameter对象,用递归的方式把它的所有属性、所有子对象全部列出来。也就是说,你在Revit里选中了一堵墙,点一下Snoop Current Selection,墙的每一个参数、每一个几何实体、每一个依赖项都会被展成树形表格。

1.2 标题里“含源码和addin”意味着什么

这个标题没有说“编译好的安装包”,而是明确写了“含源码和addin”。这说明你这套东西拿下来之后,通常会有两类内容:

  • 一类是编译好的dll文件和addin文件,可以直接复制到Revit的Addins目录里使用;
  • 另一类是完整的源码工程,可以通过Visual Studio打开、重新编译、甚至改造。

为什么这个信息很重要?因为RevitLookup这类的加载方式不是常规插件菜单,它本质上是Revit的AddIn Application,通过addin文件声明一个实现了IExternalApplication接口的程序集路径。Revit在启动时会读取addin文件,加载这个外部应用,然后由这个应用在Revit界面里注册一组外部工具按钮。

我自己的习惯是:拿到带源码的包,先不急着用现成的dll,而是自己编译一遍。因为Revit版本的API有差异,不同年份的版本对应不同的.NET Framework目标框架和引用路径,自己编译一遍至少能确认它和你本机的Revit版本是匹配的。

1.3 默认界面与五大Snoop入口

RevitLookup 2020安装成功以后,你会在“附加模块”选项卡里看到“外部工具”按钮,点开之后能看到一排Snoop入口:

  • Snoop Current Selection(查看当前选中的元素)
  • Snoop DB(查看当前文档的数据库,包括所有元素、族、视图、图纸等)
  • Snoop App(查看Revit应用程序对象,可以展开到Document,再到Element)
  • Snoop Point(拾取一个点,查看该点附近的元素)
  • Snoop Face(拾取构件上的面,查看面的几何信息)

我平时用得最多的是前两个。Snoop Current Selection适合快速定位单个元素的参数和几何;Snoop DB适合在没有明确选择对象时,按类型筛选看整个文档的数据结构。比如我想检查当前项目里所有墙的类型参数,直接进Snoop DB,过滤出Wall,再逐个点开看Type参数,比自己写一个遍历循环快多了。

2. 源码结构讲解:读代码是掌握RevitLookup的最好方式

2.1 核心工程结构

RevitLookup 2020对应的源码工程在GitHub上有明确的历史标签。这个版本整体是WinForms实现,不是后面2022版本改成的WPF风格,所以阅读门槛相对低,适合当Revit API入门的阅读素材。

整个工程的顶层目录很简单,主要就是一个csproj项目,里面包含几个最核心的代码文件:

  • App.cs:IExternalApplication实现,负责在OnStartup时往外部工具里添加菜单按钮;
  • SnoopForm.cs:所有Snoop操作的主界面窗体,树形表格的展示逻辑都在这里;
  • SnoopableObjectWrapper.cs:这个文件是整个工具的灵魂,负责把任意Revit对象包装成可展开的树节点;
  • SnoopUtils.cs:各种辅助方法,比如根据对象类型生成子节点、判断类型是否可展开等。

如果你第一次读这套源码,我建议按这个顺序读:先读App.cs,搞明白addin加载后怎么注册按钮;再读SnoopableObjectWrapper.cs,理解一个对象是怎么被递归展开的;最后再读SnoopForm.cs,看展开出来的树形表格是怎么绑定到界面上的。

2.2 SnoopableObjectWrapper:一切Snoop的“包壳”

这个类是RevitLookup最有价值的部分。它的核心思路非常简单:在.NET里,所有对象都可以通过反射来获取属性和字段。RevitAPI里的Element、Parameter、GeometryObject这些类,虽然它们内部的数据结构很复杂,但在反射面前都是可以被枚举的对象。

SnoopableObjectWrapper在内部维护了一个对象引用,同时记录了当前节点在树中的路径。在生成子节点的过程中,它先判断对象的类型,分情况处理:

  • 如果对象是Element,它就会把Element的各个分类数据展开:类别、族、类型、参数、几何、材料、阶段、设计选项等;
  • 如果对象是Parameter,它就显示参数名、参数组、存储类型、单位、当前值、是否为共享参数等;
  • 如果对象是GeometryObject(比如Solid、Face、Edge),它就递归展开到下一个几何层级。

这里有一个很多人容易忽视的细节:Revit API里很多属性是“惰性计算”的。比如Element.Geometry这个属性,你直接访问它可能返回空或者触发警告。RevitLookup在读这类属性时会走一个特殊分支,先提取GeometryOptions,再传入ComputeGeometry()可能出现的异常并做容错处理。

2.3 SnoopForm与界面交互逻辑

SnoopForm本身不复杂,核心就是基于DataGridView做树形展开。界面上有两列:一列是对象名称,一列是对象值。当你点击某个节点时,它会根据当前节点的对象类型继续生成下一层子节点,这个过程实际上就是递归调用SnoopableObjectWrapper的生成子节点方法。

阅读窗口的Navigator添加了一个展开路径栏,当你选中一行,路径栏会显示类似Document -> Element -> Geometry -> Solid -> Face这样的层级路径。这个路径对定位问题特别重要,我在实际排查几何问题时,全靠这个路径判断数据挂在哪个层级下。

2.4 编译前的准备:目标框架与引用

很多人拿到源码后直接按F5编译,结果报一堆错。RevitLookup 2020的源码默认目标框架大概率是.NET Framework 4.7.2,你在编译之前必须确认三点:

  • 本机安装了Visual Studio 2019或2022,并且安装了“.NET桌面开发”工作负载;
  • 引用的RevitAPI.dll和RevitAPIUI.dll路径指向本机安装的Revit 2020,路径一般是C:\Program Files\Autodesk\Revit 2020\;
  • 两个Revit API引用属性里的“复制本地”设置为False,否则编译输出目录会多出两个大dll,而且容易和Revit自带的API版本冲突。

我第一次编译这个项目时,就是把“复制本地”默认改成True,结果生成的dll目录里堆了一堆Revit API文件,addin加载时反而报错。后来统一改成False,干净多了。

3. Addin侧载实操:让RevitLookup 2020出现在“附加模块”里

3.1 addin文件到底怎么写

很多人分不清“addin文件”和“插件本身”的关系。插件本身就是一个.NET程序集,也就是dll。revit怎么知道要加载哪个dll呢?就是靠addin文件,它本质上是XML格式的配置文件。

RevitLookup 2020对应的addin文件内容长这样:

<?xml version="1.0" encoding="utf-8"?> <RevitAddIns> <AddIn Type="Application"> <Name>RevitLookup</Name> <Assembly>D:\RevitTools\RevitLookup\RevitLookup.dll</Assembly> <FullClassName>RevitLookup.App</FullClassName> <AddInId>5B5C2E31-3E5A-4F2B-9A0C-6B6A0B284D77</AddInId> <VendorId>ADSK</VendorId> <VendorDescription>RevitLookup Tool</VendorDescription> </AddIn> </RevitAddIns>

其中最关键的两个节点是:

  • Assembly:dll的绝对路径,或者能通过相对路径定位到的位置;
  • FullClassName:包含了完整命名空间的类名,这里就是RevitLookup.App。

AddInId是一个GUID,每个插件都应该有一个唯一ID。如果你自己改造了源码,重新生成一个新GUID即可。VendorId和VendorDescription主要用于区分厂商,不写也能加载,但规范的项目都会填上。

3.2 文件放哪里才生效

在Windows系统上,Revit 2020读取addin文件的位置是:

%AppData%\Autodesk\Revit\Addins\2020

也就是当前用户的Roaming目录。你把这个XML文件复制进去,把里面的Assembly路径改成你编译出来的RevitLookup.dll实际所在位置,然后启动Revit,在“附加模块”选项卡里就能找到对应的外部工具。

这里有个很容易踩的坑:不要把addin文件放到了Program Files下面,也不要放到了C:\ProgramData\Autodesk\Revit\Addins\2020。Revit有多个addin扫描路径,某些版本还会读取AllUsers路径下的文件,但最稳妥、最常用的就是当前用户的Roaming目录。

3.3 首次启动校准

addin文件放好之后,启动Revit,正常情况下你会看到“外部工具”菜单里出现RevitLookup相关按钮。如果看不到,不要急着重启,先检查两件事:

第一,事件查看器。去Windows事件查看器里看“应用程序”日志,如果addin加载失败,会有一条异常记录,里面会提示是程序集路径无效还是类名找不到。

第二,Revit的Journal文件。Revit每次启动都会在%LocalAppData%\Autodesk\Revit\Autodesk Revit 2020\Journals\目录下生成一个日志文件。搜索“RevitLookup”关键字,就能看到加载过程中的具体错误信息。

我见过最离奇的一次是addin文件被Windows Defender拦截了,导致Revit启动后外部工具里一片空白。后来把整个编译输出目录加入杀软白名单,问题就消失了。遇到“加了addin但不显示”的小伙伴,可以先排查杀软。

4. 实战场景:用源码改出自己定制的RevitLookup

4.1 场景一:给树节点加上“复制完整路径”

RevitLookup自带的路径栏能看到当前节点的层级路径,但它不能一键复制。我在做项目时,经常需要把某个参数的完整路径贴到聊天群里请教别人,或者贴到自己的笔记里。这时候我就会改源码,加一个右键菜单。

在SnoopForm里,DataGridView的CellContextMenuStrip上新建一个菜单项,点击后获取当前行对应的SnoopableObjectWrapper对象,然后把它的路径字段拼接成一个字符串,写入剪贴板。核心代码思路是:

private void copyFullPathToolStripMenuItem_Click(object sender, EventArgs e) { if (snoopDataGridView.SelectedRows.Count == 0) return; var row = snoopDataGridView.SelectedRows[0]; var wrapper = row.Tag as SnoopableObjectWrapper; if (wrapper == null) return; string path = GetNodePath(wrapper); // 拼接当前节点的层级路径 Clipboard.SetText(path); }

这个功能虽然小,但实际使用频率很高。尤其是你在写技术文档或给同事描述问题时,能直接复现一段“Document -> Element -> Geometry -> Solid -> Face -> PlanarFace -> Normal”这样的路径,沟通效率会高很多。

4.2 场景二:快速导出当前节点的所有参数

RevitLookup看单个参数很方便,但当你想一次性把某个元素的几十个参数全部导出到Excel或CSV时,手动点就很痛苦了。

我的做法是在SnoopForm里加一个“导出CSV”按钮,遍历当前树节点的所有子节点,取出每一行的Name和Value两列,写入CSV文件。这个改造逻辑不复杂,关键在于拿到DataGridView的行集合后,要注意区分Category、Parameter、BuiltInParameter这些不同类型节点,否则导出的数据会很乱。

4.3 场景三:和Visual Studio断点配合调试

这个技巧是进阶用法。把RevitLookup源码项目在Visual Studio里打开,把项目属性里的“启动外部程序”设置为Revit 2020的Revit.exe路径,然后按F5启动。这样Revit会像正常打开一样启动,但挂在了调试器下面。

启动后,你可以在SnoopableObjectWrapper生成子节点的代码里打上断点,然后回到Revit选中一个元素,点击Snoop Current Selection。你会发现每展开一个节点,Visual Studio都会停在断点上,你就能清楚地看到RevitLookup内部是怎么一步步反射出数据的。

这个方法特别适合理解Revit API的属性访问顺序,以及哪些属性在访问时可能会抛出异常。我看过源码之后就形成了条件反射:以后写插件遇到API调用异常,第一时间就会想这个属性是否是惰性加载、是否需要先设置上下文。

5. 常见问题与排查技巧实录

我整理了一份我在使用和编译RevitLookup 2020时遇到的典型问题,直接做成速查表,方便大家对照排查:

现象可能原因处理办法
附加模块里没有外部工具入口addin文件路径不对,或Assembly路径无效确认addin放在%AppData%\Autodesk\Revit\Addins\2020文件夹;检查dll是否真的存在
加载时提示“类名无效”或“找不到指定的文件”FullClassName和实际命名空间不一致打开源码,查看App类的实际命名空间,比如RevitLookup.App,再修改addin文件
编译报错无法加载RevitAPIUI引用的RevitAPI.dll路径错误删除现有引用,重新浏览到Revit 2020安装目录下的RevitAPI.dll和RevitAPIUI.dll
编译输出目录里出现RevitAPI等相关dll引用属性“复制本地”没设为False在解决方案里选中两个Revit API引用,把Copy Local改成False,重新生成
Snoop时某些属性显示“调用异常”Revit API属性受上下文限制,不可直接读取不用过度担心,看异常信息判断是否是正常情况;可能是需要在文档事务中访问
同一套addin在2021版本里加载失败Revit不同版本的API和框架不匹配从GitHub拉取对应版本的源码,重新编译并生成对应年份的addin文件

这里要重点提醒一下:RevitLookup 2020的addin文件只能让Revit 2020加载。如果你机器上装了Revit 2020和2021,千万不要拿同一个addin文件去复制到2021目录里。常见做法是在Addins目录下按年份建子目录,2020的放2020,2021的放2021,每个目录里放了对应版本编译的dll和addin。

还有一个我实际操作中总结的小技巧:如果你本地经常测试好几个自己写的插件,可以用同一个addin目录统一管理,不要每装一个插件就往Revit的Addins根目录扔一个XML。我习惯建一个总的工具目录,比如D:\RevitTools,下面按插件名分文件夹,addin文件里的Assembly路径全部指向这个目录里的相对路径。这样重装系统、更换电脑,整个工具链迁移过去就能用。

关于源码本身,我给个实在的建议:RevitLookup这套源码,你不需要把每一行都读懂,但SnoopableObjectWrapper.cs这个文件值得反复咀嚼。理解了它,就理解了Revit对象模型的轮廓——你写插件时遇到的大多数问题,其实都可以用“先把对象Snoop出来看一眼”来快速定位。

我自己现在写任何Revit插件,桌面上永远会留一个编译好的RevitLookup 2020,同时保存一份源码工程。遇到奇怪的API行为,第一反应不是去查文档,而是先打开RevitLookup,选中对象,一层层展开看看它的数据到底长什么样。这种“先看数据结构、再写业务逻辑”的习惯,帮我省下了大量排查时间。如果你还没试过改一套属于自己风格的RevitLookup,我建议从加一个右键复制路径的功能开始,难度小、收益高,也算正式踏进了Revit插件工具链定制的大门。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询