
简介面向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再到ElementSnoop 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.csIExternalApplication实现负责在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 version1.0 encodingutf-8? RevitAddIns AddIn TypeApplication NameRevitLookup/Name AssemblyD:\RevitTools\RevitLookup\RevitLookup.dll/Assembly FullClassNameRevitLookup.App/FullClassName AddInId5B5C2E31-3E5A-4F2B-9A0C-6B6A0B284D77/AddInId VendorIdADSK/VendorId VendorDescriptionRevitLookup Tool/VendorDescription /AddIn /RevitAddIns其中最关键的两个节点是Assemblydll的绝对路径或者能通过相对路径定位到的位置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. 实战场景用源码改出自己定制的RevitLookup4.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的放20202021的放2021每个目录里放了对应版本编译的dll和addin。还有一个我实际操作中总结的小技巧如果你本地经常测试好几个自己写的插件可以用同一个addin目录统一管理不要每装一个插件就往Revit的Addins根目录扔一个XML。我习惯建一个总的工具目录比如D:\RevitTools下面按插件名分文件夹addin文件里的Assembly路径全部指向这个目录里的相对路径。这样重装系统、更换电脑整个工具链迁移过去就能用。关于源码本身我给个实在的建议RevitLookup这套源码你不需要把每一行都读懂但SnoopableObjectWrapper.cs这个文件值得反复咀嚼。理解了它就理解了Revit对象模型的轮廓——你写插件时遇到的大多数问题其实都可以用“先把对象Snoop出来看一眼”来快速定位。我自己现在写任何Revit插件桌面上永远会留一个编译好的RevitLookup 2020同时保存一份源码工程。遇到奇怪的API行为第一反应不是去查文档而是先打开RevitLookup选中对象一层层展开看看它的数据到底长什么样。这种“先看数据结构、再写业务逻辑”的习惯帮我省下了大量排查时间。如果你还没试过改一套属于自己风格的RevitLookup我建议从加一个右键复制路径的功能开始难度小、收益高也算正式踏进了Revit插件工具链定制的大门。本文还有配套的精品资源点击获取