简介:RevitLookup 2020是一款面向Revit二次开发的辅助查找工具,适合使用Revit 2020并需要查看内部对象数据的插件开发者。它可帮助快速查询元素、类别、参数、几何等底层信息,常用于调试插件、理解API对象结构。资源包内含完整C#源码与addin配置,便于学习Revit API调用方式和工具实现细节。整个压缩包共161个文件,仅1.05MB,主要包括78个cs源码文件、Visual Studio工程(sln/csproj)、可直接复制的RevitLookup.dll与addin文件,以及bmp、ico、resx等界面资源文件;目录组织清晰,既可直接放到Revit插件目录尝试使用,也适合用Visual Studio打开源码自行更新引用并重新编译。目前已有1654人学习下载,对于正在做Revit二次开发、希望提升调试效率的开发者来说,是一份轻量且实用的参考工具。
1. 用 RevitLookup 2020 拆开 Revit 元素的黑匣子:每个二次开发者的调试刚需
写 Revit 插件时最耗时间的不是写代码,而是猜某个元素内部到底存着什么。我调一个墙的类型参数,先写循环遍历 Parameters,再用长长的条件判断过滤内置参数名,最后还得靠 MessageBox 一行行弹出来看。RevitLookup 2020 改变了这个流程:它是一个加载进 Revit 2020 的附加模块,选一个元素,点一下 Lookup,就能把墙、族、视图、尺寸标注、房间等对象的属性树完全展开——参数名、参数值、ElementId、几何引用、LocationCurve 全部呈现在你面前。这个工具源码和 addin 文件一起打包好了,拿到手可以直接编译、改、部署。适合刚接触 Revit 二次开发的人快速理解 API 结构,也适合老手在封装不熟悉的 API 对象前做现场勘察,省掉“先写一大段测试代码再猜”的时间。
2. 编译 RevitLookup 2020 源码:从解决方案到三个关键编译开关
RevitLookup 与 Revit 版本强绑定,这份源码标明 2020,就是对着 Revit 2020 的 API 程序集写的。想用在 2021 或更高版本上,得改引用替换源码,不是直接能跑。下面先解决如何把它编译成可加载的 DLL。
2.1 事前准备:先把版本和环境对齐
开发环境按常见配置来:Windows 10 或 Windows 11,装上 Visual Studio 2019 或 2022,工作负载里勾选“.NET 桌面开发”。Revit 2020 本身是 64 位进程,所以编译目标平台要么选 x64,要么选 AnyCPU,但千万别选 x86。
源码包解压后,目录里一般能看到的文件包括:
| 文件 | 作用 |
|---|---|
| RevitLookup.sln | 解决方案入口,用 VS 直接打开 |
| RevitLookup.csproj | 项目文件,里面放着引用路径和编译配置 |
| RevitLookup.addin | 插件清单,Revit 启动时靠它找到 DLL |
| App.cs | IExternalApplication 入口,负责挂载 Ribbon 按钮 |
| Snoop*.cs | 核心逻辑,负责展开对象结构 |
编译前要确认 RevitAPI.dll 引用指向正确的 Revit 2020 安装目录。很多翻车都是因为电脑上装了多个 Revit 版本,csproj 里的 HintPath 写着 2021 的路径,编译能过,加载时却各种报错。引用建议这样配:
<Reference Include="RevitAPI"> <HintPath>D:\Revit2020\Public Assemblies\RevitAPI.dll</HintPath> <Private>False</Private> </Reference> <Reference Include="RevitAPIUI"> <HintPath>D:\Revit2020\Public Assemblies\RevitAPIUI.dll</HintPath> <Private>False</Private> </Reference>逻辑说明:如果 Revit 安装在 C 盘默认位置,把路径改成对应安装目录下 Public Assemblies 文件夹的绝对地址。 设为 False 很关键——它告诉编译器不要把这几个 Revit 程序集复制到输出目录,运行时由 Revit 主进程提供。如果你把 Private 设为 True,输出的 bin 文件夹里会多出几个 Revit 的 DLL 副本,反而容易引发版本冲突。
参数说明:HintPath 是 csproj 里相对常见且稳定的引用写法;当 HintPath 指向的文件不存在时,VS 会显示黄色警告并在引用节点上标感叹号。遇到这种情况,把引用删掉重新添加,指向 Revit 2020 的 Public Assemblies,警告即消。
2.2 编译步骤:可视化与命令行两条路
最简单的做法是双击 RevitLookup.sln,等待 VS 完成加载和 NuGet 还原,然后在解决方案上右键,选择“生成解决方案”。输出路径通常是项目目录下的 bin\Release 或 bin\Debug,取决于当前配置。
如果不想开 GUI,也可以用命令行编译。以管理员身份打开“开发者命令提示符”,进入源码目录:
cd D:\RevitLookup-2020 nuget restore RevitLookup.sln MSBuild.exe RevitLookup.sln /p:Configuration=Release /p:Platform=x64逻辑说明:nuget restore 是为了拉取解决方案引用的第三方包。RevitLookup 本身依赖很少,很多版本甚至没有 NuGet 包,但顺手执行一遍没有副作用。MSBuild 是 VS 背后的编译引擎,不启动 IDE 也能出 DLL。
参数说明:Configuration=Release 让输出更干净,Debug 也没问题,只是加载后调试符号稍微多些。Platform=x64 直接产出一个 64 位程序集,规避了 AnyCPU 在不同进程环境下被意外加载成 32 位的可能。如果你在 VS 里编译,记得在“配置管理器”里确认活动解决方案平台是 x64 或 AnyCPU。
2.3 生成产物:DLL、addin、PDB 各司其职
编译成功后,打开 bin\Release 文件夹,能看到几个关键文件:
| 文件 | 作用 | 是否必须部署 |
|---|---|---|
| RevitLookup.dll | 主程序集,所有功能都在里面 | 必须 |
| RevitLookup.addin | XML 清单,告诉 Revit 加载哪个类、哪套 DLL | 必须 |
| RevitLookup.pdb | 调试符号,崩溃时能定位到具体行号 | 建议保留 |
| 其他 .dll | 第三方依赖 | 有就一起带上 |
这里有个常见误解:有人以为 addin 文件是 Revit 自动生成的,不需要管。实际上 Revit 2020 的插件加载机制是靠 addin 清单文件的,它不会扫描任意目录里的 DLL,只会读指定的 Web 服务目录和本地 AddIns 文件夹。addin 文件里写的 DLL 路径,就是最终被加载的路径。
我一般会先在编译目录里检查一遍 addin 文件是否存在。如果源码包里没带,也没关系,下一章直接手写一个,比改现成的还快。这一步的核心目的只有一个:把 DLL 和 addin 的关系理顺,后面部署才不会懵。
3. 部署与加载:addin 文件的 XML 结构和存放位置决定成败
编译成功只是第一步,Revit 认不认这个插件,完全看 addin 清单内容和你把文件放到了哪个目录。这一章把这两件事拆开讲。
3.1 addin 文件三个关键节点:Type、Assembly、FullClassName
以最常见的 Application 型清单为例,一个能用的 RevitLookup.addin 内容长这样:
<?xml version="1.0" encoding="utf-8"?> <RevitAddIns> <AddIn Type="Application"> <Name>RevitLookup 2020</Name> <Assembly>D:\RevitLookup-2020\bin\Release\RevitLookup.dll</Assembly> <FullClassName>RevitLookup.App</FullClassName> <AddInId>4F2D1B8A-7C3E-4E6B-9D44-5A1B2C3D4E5F</AddInId> </AddIn> </RevitAddIns>逐节点说明:Type="Application" 表示插件是一个外部应用,Revit 启动时就要加载,用于往 Ribbon 上加按钮;如果插件是命令,Type 要改成 Command,FullClassName 也要换成实现了 IExternalCommand 的类。RevitLookup 需要把 Lookup 按钮挂到界面面板上,所以必须走 Application 身份。
Assembly 节点写的是 DLL 的绝对路径。有人写成相对路径,结果不同机器上路径解析不一致,加载失败。我建议一律写绝对路径,顶多是换电脑后改一下。
FullClassName 是程序集中入口类的完全限定名,一定带命名空间。比如源码里入口类是 App,在 RevitLookup 命名空间下,FullClassName 就是 RevitLookup.App。写错一个字母,Revit 会提示找不到类型。
AddInId 是插件唯一标识,标准 GUID 格式。它不需要和 DLL 内部注册的东西一致,但必须保证同一个加载环境下不跟其他插件重复。生成方法很简单:Visual Studio 菜单里的“工具 → 创建 GUID”,选带连字符的格式,粘贴进来就行。
3.2 存放位置:两个 AddIns 目录和它们的优先级
Revit 2020 的插件目录是按年份命名的,和 Revit 2019、2021 的目录分开。常见的两个位置是:
| 目录 | 作用 |
|---|---|
| C:\ProgramData\Revit\Addins\2020\ | 所有 Windows 用户共享,适合团队统一部署 |
| C:\Users\你的用户名\AppData\Roaming\Revit\Addins\2020\ | 仅当前用户可见,适合个人调试 |
注意,这两条路径在不同中文系统上可能显示为“ProgramData”或“用户”等本地化名称,但目录结构一致。
放置原则:单人开发放 AppData 下即可;要给多个同事分发,放 ProgramData 更合适。若两份目录同时存在同名 addin,Revit 默认优先读取 ProgramData 下的配置,调试时先确认你改的是不是生效的那一份。
另外,别把 addin 文件直接放在 Revit 安装目录的 Program 文件夹里,那不会生效。Revit 只扫描上述两个指定的 AddIns 文件夹,其他位置一概不认。
3.3 验证加载结果:从“附加模块”选项卡看真相
把 DLL 和 addin 都放好之后,启动 Revit 2020,切换到“附加模块”选项卡,正常情况下会出现名为 LookUp 的面板或按钮。
点击按钮前先选中一个元素,再点 Lookup,窗口会弹出并展开该元素的对象树。如果按钮出现了但点完没反应,最常见的原因是当前选择的元素类型不支持 Lookup 展开,比如选中的是视口外空白区域。还有一种验证方法:在“附加模块”选项卡下,找到“外部工具”下的各类命令入口,如果这里的列表也没有 RevitLookup,说明清单没有被 Revit 识别。
到这里,插件已经能用了。接下来整理几个我实际踩过、也帮同事排查过的坑。
4. 避坑排查:RevitLookup 2020 最常见的五个加载与运行问题
越基础的工具,越容易在加载环节出幺蛾子。下面这五条按“现象 → 原因 → 解决”展开,都是实际环境中反复出现的。
4.1 加载阶段的三个高频问题
现象一:附加模块选项卡上根本没有 LookUp 按钮。
原因:addin 文件没被 Revit 扫描到,或者 XML 格式非法。很多情况下是下载的源码包里的 addin 文件编码有问题,或者 GUID 在被复制过程中丢了连字符。
解决:用记事本或 VS 打开 addin 文件,确认 XML 结构完整;把 AddInId 换成新生成的 GUID;最后确认文件确实放在 2020 这个年份目录下——我见过有人把 2020 的插件放进 2021 文件夹,症状一模一样。
现象二:启动 Revit 时弹“无法加载程序集 RevitLookup.dll”,应用直接退到编辑界面。
原因:Assembly 节点里的 DLL 路径失效,或者 DLL 引用的 .NET Framework 版本高于 Revit 2020 支持的版本。Revit 2020 默认跑在 .NET Framework 4.7 上,如果 csproj 把目标框架改成了 4.8 以上,加载时就会因运行时版本不匹配而罢工。
解决:先确认 Assembly 里的路径存在且文件名正确;再把项目目标框架改为 .NET Framework 4.7.2,重新编译,替换 DLL 后重试。这种现象在高版本 VS 新建项目时特别容易翻车,因为默认目标框架往往偏高。
现象三:点按钮毫无反应,也不报错。
原因:FullClassName 写错或加上了不存在的命名空间,导致 Revit 找不到入口类。这时 Revit 只会在日志里记录错误,界面不会有任何提示。
解决:打开 DLL 对应的源码,确认入口类名和命名空间,修改 addin 里的 FullClassName 后重启 Revit。还有一个笨但有效的办法:用任意 PE 工具打开 DLL,查看导出的类型列表,入口类一定在里面。
4.2 运行阶段的常见异常
现象四:Lookup 窗口能打开,但对象树内容为空,或者只有少部分参数。
原因:多数情况下,选中的是几何图元而不是有参数的元素,比如选了一个 SketchPlane 或 ImportInstance;也可能是元素参数本来就分为“实例参数”和“类型参数”两类,Lookup 默认展示的是实例参数,类型参数需要进一步展开 Type 节点。
解决:在 Lookup 窗口里点击元素对应的 Type 节点,看类型参数;如果是导入符号,先切换到族实例或系统族再看。这个操作逻辑其实和 Revit API 一致——Category、Parameter 和 ElementId 的基础数据都是按实例和类型分层的。
现象五:编译能过,但运行到一半崩溃,错误信息指向“版本冲突”。
原因:csproj 引用 RevitAPI 时 Private 设置为 True,编译器把 RevitAPI.dll 复制到了输出目录,同时 Revit 进程又加载了自己内部的同一份程序集,两边的程序集版本标识不一致,运行时类型传递失败。
解决:把引用里的 Private 改成 False,重新编译,删除 bin 下的旧 DLL 再部署一次。这个坑撑得上典型的“表面没问题,跑起来就炸”,排查时先看引用配置永远是对的。
5. 进阶用法:用 Lookup 反推 API 对象结构,而不是只看参数
很多人把 Lookup 当参数查看器用,这其实浪费了它最大的价值。它本质是一个“对象结构可视化器”,能从 UI 界面反推出 API 类型层次,配合少量测试代码,直接转化成你的业务逻辑。
5.1 从对象树映射到 C# 属性
拿墙举例。在 Lookup 里选中一面墙,展开根节点,能看到 LocationCurve,Width,BuildingType,StructuralUsage 等字段。这些字段名和 Revit API 里的属性几乎一一对应,我可以照着写代码:
Wall wall = doc.GetElement(new ElementId(...)) as Wall; if (wall != null) { Debug.Print("LocationCurve: {0}", wall.Location?.GetType().Name); Debug.Print("Width: {0}", wall.Width); ElementId typeId = wall.GetTypeId(); Debug.Print("WallType: {0}", doc.GetElement(typeId)?.Name); }这段代码的逻辑是:先拿到当前选中的元素,转成 Wall 类型,再用 Lookup 里看到的属性名直接取值。注意 LocationCurve 在 Lookup 里显示为一条直线数据,但它的实际类型是 LocationCurve,而 wall.Location 的返回类型是 Location,需要通过 GetType().Name 才能确认是 LocationCurve 还是 LocationPoint。Lookup 的价值就在这——它能直接告诉你运行时类型到底是什么。
5.2 用搜索框快速定位嵌套参数
族实例、房间、标注这些元素常常嵌套很深:元件 → 类型 → 参数组 → 共享参数。手动展开得点好多次,效率很低。
Lookup 的窗口顶部一般带搜索框或类型筛选功能,我通常输入大概的参数名,比如输入“Height”,它能快速过滤出所有名字里带 Height 的字段和参数。定位到目标后,直接看它属于哪个父节点,就能知道这个参数到底挂在 Element 上、ElementType 上还是某个 GeometryObject 上。这个信息比查 API 文档还直接,因为它展示的是实际运行时的对象结构。
5.3 把 Lookup 结果变成你自己的调试日志模块
看懂结构之后,下一步是把它内化成自己的工具。我常写一个通用的参数导出函数,原理和 Lookup 展开参数列表一样,只是输出目标从窗口变成文本文件:
private void DumpElementParameters(Element element, string filePath) { var sb = new StringBuilder(); foreach (Parameter param in element.Parameters) { string val; switch (param.StorageType) { case StorageType.String: val = param.AsString(); break; case StorageType.Integer: val = param.AsInteger().ToString(); break; case StorageType.Double: val = param.AsDouble().ToString(); break; case StorageType.ElementId: val = param.AsElementId().ToString(); break; default: val = "<null>"; break; } sb.AppendLine($"{param.Definition.Name} = {val}"); } File.WriteAllText(filePath, sb.ToString()); }逻辑说明:这个函数遍历元素的所有参数,把每个参数按存储类型转换成字符串,再拼接输出。它比 Lookup 多做的事是:把现场数据落地成文件,方便对比不同元素的参数差异,或者在批量处理日志里记录每次操作的上下文。
参数说明:StorageType 决定了怎么取值,这是 Revit API 里最容易忽略的细节。参数不是只有字符串一种存储方式,还有整数、浮点数和 ElementId,直接 AsString() 对某些 StoreageType 会返回空值。
写好这个工具函数后,再看 Lookup 时,它就成了我的“排错对照表”:界面里怎么看,代码里就怎么写,两者互为印证。
6. 让 Lookup 成为调试习惯:一个从对象结构直接生成日志的小技巧
从 Lookup 到自己的调试代码,其实只差一步:把看到的结构自动转化成日志文件。我的做法是在测试命令里加一个反射式的属性遍历函数,作用类似迷你版 Lookup。
public static void DumpProperties(object obj) { if (obj == null) return; foreach (PropertyInfo prop in obj.GetType().GetProperties()) { try { object value = prop.GetValue(obj, null); Debug.Print($"{prop.Name}: {value ?? "<null>"}"); } catch (Exception ex) { Debug.Print($"{prop.Name}: <error> {ex.Message}"); } } }这个函数不针对某个具体的 Wall 或 FamilyInstance,而是对任意对象输出所有属性的值。调试的时候,在可疑对象的赋值点之后调用 DumpProperties,日志里立刻能看到哪个属性是 null、哪个抛异常,和 Lookup 窗口里的层级一一对应,排查效率高出一截。
从那以后,每次收到别人的插件代码或者接触没见过的 API 对象,我都强制自己先走一遍流程:启动 Revit 2020,选中目标元素,用 Lookup 展开看结构,再动手写代码;写完业务逻辑后,如果运行结果不对,不急着猜,先加一行 DumpProperties 看看对象状态。整套流程走下来,比翻文档、猜属性、盲写循环快多了。希望帮到你。
本文还有配套的精品资源,点击获取